简体   繁体   中英

Tooltip delay on hover with RXJS

I'm trying to add tooltip delay (300ms emphasized text ) using rxjs (without setTimeout()). My goal is to have this logic inside of TooltipPopover component which will be later be reused and delay will be passed (if needed) as a prop.

I'm not sure how can I add "delay" logic inside of TooltipPopover component using rxjs?

Portal.js

const Portal = ({ children }) => {
  const mount = document.getElementById("portal-root");
  const el = document.createElement("div");

  useEffect(() => {
    mount.appendChild(el);
    return () => mount.removeChild(el);
  }, [el, mount]);

  return createPortal(children, el);
};

export default Portal;

TooltipPopover.js

import React from "react";

const TooltipPopover = ({ delay??? }) => {

  return (
    <div className="ant-popover-title">Title</div>
    <div className="ant-popover-inner-content">{children}</div>
  );
};

App.js

const App = () => {

  return (
        <Portal>
          <TooltipPopover>
            <div>
              Content...
            </div>
          </TooltipPopover>
        </Portal>
  );
};

Then, I'm rendering TooltipPopover in different places:

ReactDOM.render(<TooltipPopover delay={1000}>
                        <SomeChildComponent/>
                </TooltipPopover>, rootEl)

Here would be my approach:

mouseenter$.pipe(
  // by default, the tooltip is not shown
  startWith(CLOSE_TOOLTIP),

  switchMap(
    () => concat(timer(300), NEVER).pipe(
      mapTo(SHOW_TOOLTIP),
      takeUntil(mouseleave$),
      endWith(CLOSE_TOOLTIP),
    ),
  ),

  distinctUntilChanged(),
)

I'm not very familiar with best practices in React with RxJS, but this would be my reasoning. So, the flow would be this:

  • on mouseenter$ , start the timer. concat(timer(300), NEVER) is used because although after 300ms the tooltip should be shown, we only want to hide it when mouseleave$ emits.
  • after 300ms, the tooltip is shown and will be closed mouseleave$
  • if mouseleave$ emits before 300ms pass, the CLOSE_TOOLTIP will emit, but you could avoid(I think) unnecessary re-renders with the help of distinctUntilChanged

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM