-
-
Save atomiks/520f4b0c7b537202a23a3059d4eec908 to your computer and use it in GitHub Desktop.
| // Will only render the `content` or `render` elements if the tippy is mounted to the DOM. | |
| // Replace <Tippy /> with <LazyTippy /> component and it should work the same. | |
| const LazyTippy = forwardRef((props, ref) => { | |
| const [mounted, setMounted] = useState(false); | |
| const lazyPlugin = { | |
| fn: () => ({ | |
| onMount: () => setMounted(true), | |
| onHidden: () => setMounted(false), | |
| }), | |
| }; | |
| const computedProps = {...props}; | |
| computedProps.plugins = [lazyPlugin, ...(props.plugins || [])]; | |
| if (props.render) { | |
| computedProps.render = (...args) => (mounted ? props.render(...args) : ''); | |
| } else { | |
| computedProps.content = mounted ? props.content : ''; | |
| } | |
| return <Tippy {...computedProps} ref={ref} />; | |
| }); |
| // Partially lazy | |
| // Will only mount all <Tippy /> content once the singleton itself is mounted. | |
| function PartiallyLazySingleton() { | |
| const [source, target] = useSingleton(); | |
| const [mounted, setMounted] = useState(false); | |
| return ( | |
| <> | |
| <Tippy | |
| onShow={() => setMounted(true)} | |
| onHidden={() => setMounted(false)} | |
| singleton={source} | |
| /> | |
| <Tippy content={mounted ? <ExpensiveComponent /> : ''} singleton={target}> | |
| <button>Hello</button> | |
| </Tippy> | |
| <Tippy content={mounted ? <ExpensiveComponent /> : ''} singleton={target}> | |
| <button>Hello</button> | |
| </Tippy> | |
| </> | |
| ); | |
| } | |
| // Fully lazy | |
| // Will only mount the content if that is the currently used singleton content. | |
| function LazySingleton() { | |
| const [source, target] = useSingleton(); | |
| const [mountedRef, setMountedRef] = useState(null); | |
| const ref1 = useRef(); | |
| const ref2 = useRef(); | |
| return ( | |
| <> | |
| <Tippy | |
| onTrigger={(_, event) => setMountedRef(event.currentTarget)} | |
| onHidden={() => setMountedRef(null)} | |
| singleton={source} | |
| /> | |
| <Tippy | |
| content={mountedRef === ref1.current ? <ExpensiveComponent /> : ''} | |
| singleton={target} | |
| > | |
| <button ref={ref1}>Hello</button> | |
| </Tippy> | |
| <Tippy | |
| content={mountedRef === ref2.current ? <ExpensiveComponent /> : ''} | |
| singleton={target} | |
| > | |
| <button ref={ref2}>Hello</button> | |
| </Tippy> | |
| </> | |
| ); | |
| } |
Using LazyTippy, I'm getting the following warning in my testing suite:
%chide() was called on a destroyed instance. This is a no-op but indicates a potential memory leak.
It won't happen running a single test, and even if I delete the one it breaks on, it'll just break on another.
Update: we unfortunately have to back out of using Tippy as our test suite doesn't allow warnings and I'm afraid we wouldn't be able to figure this out on our own.
<LazyTippy><LazyTippy><div>Test</div></LazyTippy></LazyTippy>
^--- Nesting multiple lazy tippies gives the error "Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?"
Any ideas on how to make nesting work?
@wahlstedt you need to forwardRef() https://github.com/atomiks/tippyjs-react/blob/master/src/forwardRef.js
Updated the example.
Can some add a lazy headless singleton example?
Thanks
Instead of
onMountto set the mounted state to true, you could tryonShowin the Lazy example for the moveTransition.