Получается этот способ заменяет использование двух хуков useCallback и useRef, которые можно было бы заюзать что бы решить эту задачу по другому, на один useMemo, так?
@@it-sin9k в документации написано, что Реакт потенциально может "забывать" о том, что хранится в useMemo. Тогда потеряются замыкания. Так что лучше было бы всю конструкцию запилить через useRef
@@alexandroppolus После изучениях исходников useMemo, мне кажется, что шанс потерять состояние имеется ввиду, что мы можем написать так себе код из-за которого что-то потеряем)
Тоже подумал про useRef для этой задачи, мне кажется, это было бы более хорошим решением с точки зрения читабельности кода) Меньше думать другим разрабам)
@@nickolayivanov2848 согласен. Для разработки в команде такой код выглядит неуместным, потому что экономит всего один хук useRef, но идёт в разрез с назначением реакт хуков.
Интересный трюк. Не знал о нём, спасибо. Вообще побольше бы контента о таких "фишках". Последнее, что из подобного слышал - использование атрибута key для быстрого unmount->mount компонента, чтобы вернуть его дефолтное состояние при инициализации. Однозначно лайк!
А не получается так, что вдруг если функция в useMemo не будет чистой (она будет использовать стейт компонента или пропсы), то появятся зависимости у useMemo, изменение которых будет сбрасывать prevFilters? Если же зависимости не добавлять вторым аргументом в useMemo, то значения зависимостей внутри тела будут из замыкания первого рендера, т.е. неактуальными. Либо я не понял идею
Да, вы все правильно поняли. При изменении зависимостей вся мемоизация перезатирается. Это может как быть полезным так и вредить. В некоторых ситуациях нужно сбросить мемоизированные данные и зависимости, это один из таких способов
Всегда в таком случае, создаю объект инишиал фильтров, какой-то хендлер меняет значения полей этого объекта, он в свою очередь прокидывается в метод где мы что-то геттим с фильтрами, а сам метод срабатывает каждый раз в юзэффекте, если мы поменяем какой-то фильтр в объекте, так как объект с фильтрами указан в массиве зависимостей юз эффекта. Так плохо делать?
Благодарю за видео. Вопрос может глупый и все же - мы сохраняем параметры фильтров и если они не изменились, повторный запрос на сервер не отправляется. Но, допустим ситуацию, что у нас в базу добавились новые аппартаменты за это время. Получается, что у нас два источника истины и пока мы не перезагрузим страницу, новые аппартаменты не добавятся. Это норма или все таки что-то не так?
Это вопрос скорее про логику приложения. Как часто вы должны загружать данные с сервера. Можно хранить и в sessionStorage и пока табу не закроют будут данные, можно в localStorage и вообще долго будут храниться данные. а можно на любой чих перезапрашивать. А можно по сокетам или SSE получать уведомление, что нужно обновить квартиру. Я пытаюсь показать, что такого рода вещи надо с бизнесом согласовыввать, как часто им нужно актуализировать данные и на какие события :)
Вопрос по поводу прикрепленного комментария о том, что данный способ заменяет useCallback и useRef. У себя запустил тестовый пример, где просто изменяю счетчик у родительского компонента App и передаю функцию в дочерний компонент List. Сама функция возвращаемая из useMemo не мемоизируется, т.к. на каждое изменение счетчика происходит ре-рендер компонента List. А с хуком useCallback мы можем мемоизировать ссылку на функцию. Причем тут тогда замена хука useCallback ?) const asyncFunc = useMemo(() => { return async () => { return 1; } }, []) return ( setCount(prev => prev + 1)}>Клик {count} );
Чего это она не мемоизируется, все она мемоизируется. Вот даже ваш пример попробовал. компонент не рендерится, при изменении счетчика codesandbox.io/s/competent-worker-p4prl4?file=/src/App.js
@@it-sin9k блин, точно. Я дочерний компонент List не обернул в memo. Получается мы вместо useCallback-а можем мемоизировать ссылку на функцию, возвращая ее в качестве значения из useMemo. Спасибо за ответ)
увидел у тебя async/await в хуках - я часто вижу у разрабов, как они забивают на асинхронность в компонентах и работают будто это синхронный код, но это может вызывать ряд проблем - ошибки и утечки памяти. А возникают они из-за того, что компонент может обновиться пока асинхронное действие в процессе, или вообще быть отмонтирован. Я дума. это хорошая тема для раскрытия. Новичкам в первую очередь стоит рассказать про такие проблемы и чем они грозят, хотя я переучивал и сеньеров
@@sharkman6434 ты можешь писать с async/await, но тогда тебе после каждого await надо убеждаться что компонент не отмонтирован и твой эффект не перевызвался, ну или функция не перевызвалась если ожидается последовательность, в общем за этим надо бдить, и помнить, что пока промис не разрешится твое замыкание будет держать компонент в памяти, и если у тебя такой промис завис навечно, а компонент отмонтировался, он зависнет у тебя навсегда потому я такие вещи выношу в более подходящие слои
Оу, а это точно бестПрактис? Я новичок, но я б просто в компонент с формой повесил бы useState с состоянием последнего фильтра. А на обработчике сабмита формы в самом бы начале сравнивал состояние формы и последнего фильтра. И если бы они равны, то вообще бы ничего не делал - return; Можно сериализовать состояние фильтра в строку и хранить его в useState. Сравнение строки со строкой мгновенное, никаких ререндеров, и, если уж меняться производительностью, то вряд ли этот вариант что либо покроет.
Да, и дату в состояние последнего фильтра подвесить. И проверять её с точностью до 5 минут. Если пользователь 10 минут пил кофе и через 10 минут решил на той же странице те же параметры ввести, то кто-то уже мог снять квартиру и список квартир будет другой - надо бэк запросить всё-таки.
Интересно, можно ли с помощью этого трюка организовать эмуляцию 'component did update' из useEffect (исключив первый рендер) ? useEffect(() => { let initialMount = true; if (initialMount) { initialMount = false; } else { //....... } } }, [...deps]);
так работать не будет - надо эту самую initialMount в useRef засунуть или использовать что-то типа import { useEffect, useRef } from react; const useFirstRender = () => { const firstRender = useRef(true); useEffect(() => { firstRender.current = false; }, []); return firstRender.current; }; export default useFirstRender; how to use const isFirstRender = useFirstRender(); useEffect(() => { if (!isFirstRender) onFilterOrders(); }, [stateFilter.subjectGroups]);
@@it-sin9k почему то не открывается ссылка хм, в конце видео где ты говоришь "Чао" после этого с права внизу есть твоя аватарка и вокруг неё синяя анимация, так же в центре есть что-то типа сферы и вокруг неё синии линии летают
Дружище, классные по содержанию видосы, но имхо почти невозможно воспринимать речь, когда ты искусcтвенно держишь темп и выделяешь каждое последнее слово предложения. Глянул твой часовой доклад - прекрасная речь, никаких проблем, было бы просто замечательно, если бы ты в такой же естественной манере говорил в анимированных роликах.
Ты прямо по больному) я же записываю кусками, и зачастую перезаписываю раз 5-6 кусок и темп то сбивается, то ускоряется. Короче крайне коряво получается. Пока не знаю как это побороть :(
@@it-sin9k ну это понятно, просто старайся естественно говорить, как-будто с кем-то разговариваешь, у тебя хорошая речь в долгих видосах, которые ты очевидно записывал одним дублем и не редактировал - меньше сил будешь тратить на видосы и будет лучше получатся.