import { useEffect, useRef, useState } from 'react' export const useEffectOnce = (effect: () => void | (() => void), vars?: React.DependencyList) => { const destroyFunc = useRef void)>() const effectCalled = useRef(false) const renderAfterCalled = useRef(false) const [_, setVal] = useState(0) if (effectCalled.current) { renderAfterCalled.current = true } useEffect(() => { // only execute the effect first time around if (!effectCalled.current) { destroyFunc.current = effect() effectCalled.current = true } // this forces one render after the effect is run setVal((val) => val + 1) return () => { // if the comp didn't render since the useEffect was called, // we know it's the dummy React cycle if (!renderAfterCalled.current) { return } if (destroyFunc.current) { destroyFunc.current() } } }, vars) }