Intentando implementar una tubería observable rxjs en React.
Ejemplo de Codesandbox -> https://codesandbox.io/s/optimistic-fog-xtdi4
Crear un elemento html (div) en React y vincular los eventos mouseover y mouseout.
Código de reacción para inicializar esto:
useEffect(() => { const elMouseOut$ = fromEvent(elRef.current, "mouseout").subscribe(() => setState({ hover: "mouseout", eventType: "mouseout" }) ); const elMouseOver$ = fromEvent(elRef.current, "mouseover") .pipe(debounceTime(2000)) .subscribe(() => setState({ hover: "mouseover", eventType: "mouseover" }) ); return () => { elMouseOver$.unsubscribe(); elMouseOut$.unsubscribe(); }; }, []);Criterios de aceptación Trámites.
He probado varias combinaciones diferentes de operadores, pero no puedo hacer que las cosas funcionen como se esperaba.
Nota: Si se cumple el tiempo de rebote del mouse sobre, se realiza una solicitud ajax.
Cualquier ayuda/consejo sería apreciado, simplemente no tengo las habilidades de rxjs para solucionar este problema.
Esto debería hacer el trabajo:
useEffect(() => { const elMouseOver$ = fromEvent(elRef.current, "mouseover"); const elMouseOut$ = fromEvent(elRef.current, "mouseout"); const mouseoutSub = elMouseOver$.pipe( debounceTime(2000), tap(() => setState({ hover: 'mouseover', eventType: 'mouseover' })), switchMap(() => elMouseOut$), tap(() => setState({ hover: 'mouseout', eventType: 'mouseout' })), takeUntil(scheduled(elMouseOut$, asyncScheduler)), repeat() ); return () => mouseoutSub.unsubscribe(); }, []);Caudal:
debounceTime : después de pasar el mouse, espere 2 segundostap - establecer el estado del mouseoverswitchMap - escuchar elMouseOut$tap - establece el estado mouseouttakeUntil : finaliza la transmisión cuando se produce el mouseoutrepeat Dado que switchMap y takeUntil usan la misma fuente, utilicé la scheduled dentro de takeUntil para que switchMap tuviera la oportunidad de emitir antes de que se completara el observable.
Aquí hay un StackBlitz que demuestra este comportamiento.
Creo que esta podría ser una forma de solucionarlo:
const sub = merge( elMouseOver$.pipe( // Step 4) // Repeating the steps with the help of `switchMap` switchMap(() => timer(2000).pipe( // Step 2). // Cancelling the stream and setting some state(have a look at '3)', below). takeUntil(elMouseOut$), // Step 1). // This will be invoked if 2 seconds have passed after the mouseover event without // the mouseout event taking place. tap(() => setState({ hover: "mouseover", eventType: "mouseover" })), ) ) ), // Step 3). // Setting the state. elMouseOut$.pipe( tap(() => setState({ hover: "mouseout", eventType: "mouseout" })) ) ).subscribe(); Además, debido a que nos estamos suscribiendo a elMouseOut$ varias veces, es posible que desee utilizar el operador share() para que solo se agregue un detector de eventos:
const elMouseOut$ = fromEvent(elRef.current, "mouseout").pipe( share(), );