javascript - RXJS 可观察量在鼠标悬停事件后取消鼠标悬停流

标签 javascript reactjs rxjs

尝试在 React 中实现 rxjs 可观察管道。

Codesandbox 示例 -> https://codesandbox.io/s/optimistic-fog-xtdi4

在React中创建一个html元素(div),并绑定(bind)mouseover和mouseout事件。

react 代码来初始化它:

   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();
    };
  }, []);

验收标准步骤。

  1. 当我将鼠标悬停时,延迟 2 秒后我需要进行状态更新。
  2. 如果我在 2 秒延迟之前的任何时间将鼠标移出,我需要取消鼠标悬停流,并设置一些状态。 (此步骤已损坏)
  3. 如果我在 2 秒延迟后的任何时间将鼠标移出,我需要设置一些状态。
  4. 这应该是可重复的,因为如果我将鼠标悬停、鼠标移出并再次悬停,我们将从第 1 步开始。

我尝试了几种不同的运算符组合,但无法使事情按预期工作。

注意:如果满足鼠标悬停去抖时间,则会发出 ajax 请求。

任何帮助/建议将不胜感激,我根本没有 rxjs 能力来解决这个问题。

最佳答案

CodeSandbox solution .


我认为这可能是解决这个问题的一种方法:

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();

此外,由于我们多次订阅 elMouseOut$,您可能需要使用 share() 运算符,以便仅添加一个事件监听器:

const elMouseOut$ = fromEvent(elRef.current, "mouseout").pipe(
  share(),
);

关于javascript - RXJS 可观察量在鼠标悬停事件后取消鼠标悬停流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68716982/

相关文章:

javascript - 如何在 React 中加载 MathJax?

javascript - 在网站中设计图像幻灯片

javascript - 在引导框对话框中使用 Blaze.render - 出现奇怪的错误

reactjs - 如何更改 material-ui-pickers 时间选择器时区?

reactjs - Material UI 选择器 - Jalali 日历问题

angular - Rxjs - 重新订阅取消订阅的 Observable

Angular/RxJs - 使用 take(1) 取消订阅依赖的 http 服务?

php - 我的 PHP 联系表无法发送

reactjs - 在 Material UI 中使用样式组件应用单选按钮颜色?

javascript - 无法解决在 typescript/webpack 中找不到模块 'rxjs'