Было непросто найти работающее решение о том, как периодически запускать memo-safe функцию из функционального компонента.
Говоря о «безопасности мемо», я имею в виду случаи, когда целевая функция ссылается на состояние компонента (которое меняется во времени).
Я решил вообще пропустить запоминание, так как:
- Использование аргументов целевой функции в качестве предикатов очень затратно в JavaScript, если они (аргументы) не являются скалярами.
Object
экземпляры равенство всегда будет открытым вопросом в JavaScript, поэтому сравнение неизменяемых предикатов для правильного использованияuseMemo
илиuseEffect
в большинстве случаев может быть более сложной операцией, чем вызов нескольких дополнительных незапоминаемых обратных вызовов (если вы, конечно, не имеете дело с анимацией) . - Я прошелся по кодовой базе своего текущего проекта и буквально не нашел ни одной целевой функции, которую нужно использовать в таком хуке и которая не ссылается на состояние вызывающего компонента.
Вот мой крючок:
const isInFocus = () => ( document === undefined || document.visibilityState === undefined ) ? true : document.visibilityState === "visible" function useClock( func: Function, delay: number, skipUnfocused = false ): void { const funcRef = React.useRef<Maybe<Function>>() React.useEffect(() => { funcRef.current = func }, [func]) React.useEffect(() => { const exec = () => { if ( !funcRef.current || (skipUnfocused && !isInFocus()) ) return funcRef.current() } const i = setInterval(exec, delay) return () => clearInterval(i) }, [delay]) }