какой-то содержательный ответ.
Зачем при мемоизации колбэков через реф делать присваивание значения рефу в useLayoutEffect или useInsertionEffect?
https://github.com/scottrippey/react-use-event-hook/blob/main/src/useEvent.ts
Можно же сделать просто так
function useEvent(callback) {
const latestRef = React.useRef();
const stableRef = React.useRef(null);
if (latestRef.current !== callback) {
latestRef.current = callback;
}
if (!stableRef.current) {
stableRef.current = function () {
return latestRef.current.apply(this, arguments);
};
}
return stableRef.current;
}
Кажется, как будто оборачивание latestRef.current = callback; в use*Effect тут лишняя конструкция, которая ничего важного не делает.
Я что-то упускаю, да? )
с первого взгляда ощущеие что в https://github.com/scottrippey/react-use-event-hook/blob/main/src/useEvent.ts весь смысл useEvent теряется 🤔 так useInsertionEffect будет на каждый рендер подменять колбек на новый…
Не, там меняется cb в latestRef, а возвращается stableRef.
а) ну да… ну тогда в этом есть смысл. У тебя сама ссылка внешняя будет всегда одна, но внутри будет всегда вызываться разная функция
Аналогично будет работать и если выкинуть из цепочки use*Effect, вопрос в этом, зачем оно тут )))
есть подозрение что есть какие-то edge кейсы, которые не очевидны на первый взгляд… я думаю стоит задать вопрос автору)
а в твоем кейсе есть смыл в проверке? if (latestRef.current !== callback) { latestRef.current = callback; } с чего бы при ререндере колбеку быть не другим? То если в callback пришла мемоизированая функция? Но такой кейс как будто бы бессмысленный (я еще не проснулся - могу тупить)
вот этот тест упадет при твоей реализации https://github.com/scottrippey/react-use-event-hook/blob/main/src/useEvent.test.ts#L62 в чем смысл его я не знаю, возможно эта была просто реализация предлагаймого useEvent в самом реакте, и у него было такое поведение
а тут что думаешь @abpstd
В кейсе с use*Effect присваивание коллбэка будет происходить только если он поменялся. Добавил сюда такую проверку только, чтобы сохранить это поведение. Сходу не вижу, чтобы тут могли быть какие-то проблемы, если её убрать и прямо в рендере написать latestRef.current = callback;
if (latestRef.current !== callback) { latestRef.current = callback; } === latestRef.current = callback;
вот мне тоже так показалось
А, ну да, чёт туплю, получается, что эта проверка вообще ничего не делает по факту XD
if (latestRef.current !== callback) { latestRef.current = callback; } else if (latestRef.current = callback) { latestRef.current = callback } Поправил
В useEvent прикол, что состояния компонента при рендере и триггере события теоретически могут разъехаться (детали не помню, там rfc читать надо) Поэтому колбек синкается в эффекте, чтобы гарантировать единый контекст
благодарю за наводку на инфу!
мы пока нашли другой ответ) Render methods should be pure, especially when concurrency is used, so we will throw this error if the callback is called while rendering.
хотя опять же такое решение не гаратирует ничего) if(notFirstRender) { callback() } 😏
Обсуждают сегодня