Выключэнне функцыі Latest-Value Ref: Адзінкты эфекта з useEffectEvent
Дазвольце даклэ расказаць, як функция useEffectEvent у React 19.2 аддзеля нерэакtyўную логіку ад эфекта, усуняе нештатныя способы выкарыстоўвання ref з памятайчым значэннем, і калі гакі хук ўсё-такі не являецца правым інструментам.
У багацькох проектах на React є элемент useRef, якім прагнець толькі зберагчы “пасляпэўшуюе значэнне”, каб эфект не быў залежным ад яго. Штучка працуе, але спрыважвае намер. У React 19.2 элемент useEffectEvent стаў стабільным, чым даны патэрн атрымаў статус хука першага класу. У канцы вы зможазеце раздзеліць рэактыўную і нерэактыўную логіку ўнутры эфекта, а таксама зразумеце, калі хук не паслужыць.
Масэва залежнасцяў, якая не можа выграць
Конфлікт выступае ў разы давгачасных з’яўленняў: чат-камнатах, стрімах через WebSocket, сесіях аналітыкі, падпісах. Элемент ChatRoom прымеў roomId і theme. Эфект должен паўтарна наладзіць з’яўленне, калі зменяецца roomId, але чытае theme толькі для стылювання паведамлення пасля наладжэння.
Дадзіце theme у массив залежнасцей, і пераход на темную модулі без прычыны знішчае сокет. Якщо яго не дадзіць, правіла лінтингу скаржаюцца; якшо іх замовчыць, калебак падтрымвае theme, зафіксаваны ў старым рэндеры, што являе сабою класычны прыклад застарэлага клоузура.
function ChatRoom({ roomId, theme }) {
useEffect(() => {
const connection = createConnection(roomId);
connection.on('connected', () => {
showNotification('Connected!', theme); // stale after theme changes
});
connection.connect();
return () => connection.disconnect();
}, [roomId, theme]); // theme shouldn't trigger a reconnect
}
Рашэнне, якое выкарыстоўвалі большасць команд
Звычны спосаб быў копіюваць theme у ref пад час кожнага рэндеру і чытаць ref.current у калебаке. Цэе працуе, але шаг сінхронізацыі лёгка забыць, і ніч у кодзе не паказвае, што логіка свядома ўзначна нерэакtyўная.
Раздзеленыя логікі запуску падзеяў за дапамогою useEffectEvent
useEffectEvent выдзеляе нерэакtyўную частку эфекту ў самастоятнюю функцыю. Гэтая функцыя завжды бачыць найновейшыя пропсы і стан, ўвокаліванне яе ніколі не перзапускае эфект, і ёй не дадаёцца месца ў массиве залежнасцей.
Нижэйшыя часткі коду паказваюць, як утвараецца прыемніка паведамленняя onConnected. Ёго дзеянне заключаецца толькі у стварэнні з’ёднання, рэгістрацыі прыемніка, падключэнні і роз’ўязванні з’ёднання пад час чысткі.
import { useEffect, useEffectEvent } from 'react';
function ChatRoom({ roomId, theme }) {
const onConnected = useEffectEvent(() => {
showNotification('Connected!', theme); // always fresh, never a dependency
});
useEffect(() => {
const connection = createConnection(roomId);
connection.on('connected', () => onConnected());
connection.connect();
return () => connection.disconnect();
}, [roomId]); // only roomId matters now
}
Як залежнае значэнне застаёцца толькі roomId. theme не быў схованы ад інструменту лінтингу; ён быў перекласыфікаваны. Аплявленне паведамлення праз toast калі стварываецца з’ёднанне — это рэакція на падзею, таму гэта ўжо логіка падзей, а не сінхронізацыя. Змена тэмы больш не падключае занова, і наступнае паведамлення все равно відображаецца ў тэме, якая ў даны момент выкорыстоўваецца.
Канцэптуальна гэта тое, што робіў хак з ref уручну: React прымае функцыю, яку вы вызываеце з эфекту, так, каб яна вказвала на закрыцце пасляльнейшага рэндару, і тады намер стае зрозумелым.
Што вы отрымаеце
- Больш няма застарэлых закрыццяў. Эфект-падзея чытае найновейшыя значэнні без неабходнасці ручных апдэйтаў ref.
У дакументах React з эры React 18 прасілі разработчыкаў аддзеляць падзеі ад эфектаў; версія 19.2 нарэшце падтрымае гэтыя рэкамендаціі за дапамогою стабільнага хука. Па іншым праблемам адзірніце нашый аптак у формате React 19.2: Activity, useEffectEvent і статычная рэндарызацыя.
Перш чым яго вжываць
useEffectEvent не заменяе useEffect, і ён не ўсунець узагальнёны спосаб для скорачэння массиваў залежнасцяў.
- Ўжыце яго толькі тады, калі змена значэння не павінна перазапускать эфект. Якщо ж павінна, значэння трэба разместіць у масе.
- Ніколі не вызывайце Effect Event пад час атрыбутавання; вызывайце яго з усередзіння эфектаў, такіх як калебачыцья падпісаў або таймеры.
- Залічвайце яго локальна для сваёй складовай, а не перадавайце яго дзецям як проп.
- Якщо большая частка эфекта знаходзіцца ўнутрь Effect Event, логіка, верагодна, павінна быць у звычным працоўніку адбудов.
До версіі 19.2 гак існаваў толькі ў эксперыментальных версіях, таму проекты на 19.0 або 19.1 павінны апгрэйдавацца, каб выкарыстоўваць стабільны API.
Ключовыя выводы
- Кожны спосаб «зберагчы найновейшае значэння ў ref» яўляецца кандыдатам на викорыстоўванне
useEffectEvent. - Для кожнай залежнасці запытайце ся, чы рэшта эфекта павінна перазапускаться; якщо няма, код, які яго чытае, ўжо є логікаю адбудовы.
Спадні матэрыялы
- Выбір правильнага інструмента для React: Derive, Handle, Fetch, Defer чы Effect — Каратацкі для прымэры замены рефлексіўных вызоваў useEffect на выведзеныя значэння, обрабоцчыкі зместоў, шар дадзеных, useTransition, measured useMemo і API React 19.
- Паставіць канец сінхронізацыі стану з useEffect: Безпечнейшы патэрн у React — Дазвольце дазнацца, чаму викорыстоўванне useEffect для сінхронізаціі выведзенага стану спрычыняе супербегі і дадатковыя перрадзены, а таксама як заменіць яго на выведзэнне пад час перрадзення і атрыбут key.
- Стварыце «іграшку» useState, каб зрозумець snapshot’ы, абаранты і эфекты — Навучыцеся, як працююць хукі React, стварыўшы маленькі useState, а пасля выкарыстоўваючы гэты модель для пояснення абарантоў апдэйтаў, застарэлых snapshot’аў, клаудзуры, чысткі эфектаў, refs і групавання задач.
- Асінхронныя формы ў React 19 з use, useActionState і useOptimistic — Як use(), useActionState, useFormStatus і useOptimistic заменяюць ручныя механізмы завантажэння і пазначэння адносов на бягу ў React 19, а таксама якія падступы крыюць кожны з гэтых хуків.
- Замена застарэлых залежнасцяў на JavaScript: CRA, Moment, jQuery і іншыя — Калькі бібліятэкаў і інструментаў на JavaScript трэба поступова адмовіцца ад іх выкарыстання, чаму кожны з іх стаў прычынай проблем, што можа іх заменіць, і як запобець таму, каб вашы список залежнасцяў зноў не пастаў проблемай.