Двадцать запитанняў для інтэрв’ю React, які адзначаюць разліку межы вжывання та розумэння
Вярчыны DOM, ключы, эфекты, мемаізацыя, Контэкст, SSR і гідратацыя — адказанае пра проблемы, якія на самай справе выявляюць адзінавальнікі, а не пра стандартныя вакласовыя апісанні.
Розробка на React і пояснэнне прынцыпаў React — гэта разныя навыкі. У адборах спрашваюць пра другі навык: што адбываецца пад час вызвання setState, чаму важлівы ключы, калі перзапускаюцца эфекты. Нижэйшыя двадцать запитання часта з’являюцца. Адпаведзі спрываюцься на проблемы, якія рашае кожны функцыянал, і на непрыемныя ситуацыі, якія выступаюць у працэйнай средзе — а не на заучаныя тэксты.
1. Чаму ўсё-такі існуе Вярчыны ДОМ
Вярчыны ДОМ не ўжо чародзейскі порошак для прыяўлення скорасці. Це звычны дрэва JavaScript, якое описвае, як павінна выглядаць інтэрфейсная частка. Калі змянюецца стан, React стварае новае вярчыны дрэва, порівнюе яго з пярэднім і супрацоўвае, прыкладаючы да рэальнага ДОМ браузера толькі неабходныя змены. Работа з рэальным ДОМ спрычыняе перзапіс паведамленняў та адрасаванне элементаў; мутацыі об’ектаў JavaScript коштаюць мало, таму React викорыстоўвае ресурсы CPU ў памяці, каб зашчадзіць ресурсы браузера. Такі падход спрямованы на мінімізацыю навантажэння на браузер, а не на тое, каб кожна параджка была безкоштовная. Заява «Вярчыны ДОМ завжды быстрейшы» без гэтай нюансаў — частая памылка начальных разработчыкаў.
2. Вярчыны ДОМ проты ДОМ браузера
Рэальныя апдэты DOM ўскладнены і можу спрычыняць перераспалоўку та перамальёванне элементаў. Вярчынныя апдэты — это разлікі об’ектаў у памяці; React групавае дорогі запісы ў DOM замест таго, каб выконваць іх па разу за кожны вызов функцыі стану. Рэдагаванне за дапамогою track-changes краща, чым перапісванне всіго документа за кожную памылку.
3. Чаму ключы ліста важлівыя, калі рядкі перамешчаюцца
Ключы ідентыфікуюць элементы праз усе перрэнды. Без іх React выкарыстоўвае позіцыю індэкса, што ламаецца, калі элементы дадаюцца, выкарыстоўваюцца або пераранжуюцца. Выкарыстоўванне індэкса масіва як ключа “функцыонуе” пакуль пераранжаванне не прыводзіць да таго, што полья та прабламы залишаюцца пры неправільных рядках — гэта фальшывы “утэк стану”, які на самай працоўцы ёсць багам з ключамі. Лепш выкарыстоўваць стабільныя, унікальныя ID з дадзеных; індэксы паслужыць толькі для сапраўдна статычных лістоў. Якщо продукт падтрымляе пераранжаванне за дапамогою ператасквання або фільтрацыю, індэксы як ключы зрэшты спакалююць локальны стан рядкаў.
4. Паспяшнае раз’ясненне useState на адных прыняцых прынцыпах
Звычныя элементы інтэрфейсу гінуць, калі функцыя вяртаеся. useState дае функцыйнаму компоненту стойкую памяць і запланаваў перыскаляванне, калі гэтая памяць змінюецца:
const [count, setCount] = useState(0);
count — гэта текущая значенне; setCount запрашвае апдэйт. Апдэйт не прыкладываецца падчас самага перыскалявання: логаванне count адразу пасля setCount все равно паказвае пярэднюе значенне, таму што новая цінная дань з’являецца толькі пад час наступнага перыскалявання.
5. Чаму апдэйты useState здаюцца затрымленымі або групаванымі
React групавае апдэйты, якія падаюць у одну і тую ж подыю, ў адна перыскаляванне. Зачынення React 18 гэтае групаванне распрастраняецца таксама на праграмы-обявы і таймеры, а не толькі на працоўнікі подый React. Калі вам патрэбна найновейшая цінная дань на адной з пярэдніх станоў, выкорыстаюце функцыйны апдэйтар:
setCount(prev => prev + 1);
Этот формат чытае найсвежэйшую значэнне з лісты, а не застарелы фотакап скарынкі. Адзінавальнікі часта запытваюць, што будзе, якшо вы скрыёте count унутрь таймауту без формату апдэйта.
6. Какую проблему на самай справе рашыяе useEffect?
Рэндараванне павінна быть чыстай функцыяй з пропсаў і статау ў JSX. Аплікацыі таксама запрашоўваюць дадзеныя, прыкладзаюць аслухальнікі змаганняў, плануюць таймеры і вплываюць на DOM — гэта пабочныя эфекты. useEffect выкананае гэтае нечыстая робота пасля адкладання, а не падчас рэндаравання:
useEffect(() => {
const id = setInterval(() => console.log("tick"), 1000);
return () => clearInterval(id); // cleanup
}, []);
Функцыя чысткі, якая вяртаецца, выкананае раней за наступны эфект і пад час зняцья. Якшо яго праігнораваць, адзінавальнікі запытваюць пра дублікаты таймероў і аслухальнікаў, якія продовжаюць працаваць пасля зняцья.
7. Чым на самай справе керуе массив залежнасцяў?
Ён паведамляе React, калі трэба зноў выканаць эфект, праз паверхневыя порэвання:
[]— адзін раз пасля маунтаў[count]— знову, калі змянюеццаcount- не выканана — пасля кожнага рэндару (рэдкасцю бывае патрабавана)
Якщо забыць значэнне, якое апісанае ў масе, то будзе створвацца старэе закрыцце: такі стан заставае першае зафіксаванае значэнне назаўсёды. Існуюць правіла праблэм-детектавання, якія пераглядаюць усе залежнасці, таму што такія багі ўзнікаюць дужа часта.
8. Контролюваныя vs неконтролюваныя компоненты
Контролюваныя элементы вучаць value з стану React і апдэйтуецца через onChange; правда належыць React.
Неконтролюваныя элементы зберагаюць стан DOM; яго чытаюць через ref, калі гэта неабходна (часта пад адправкай даных).
// Controlled
<input value={name} onChange={e => setName(e.target.value)} />
// Uncontrolled
<input ref={inputRef} defaultValue="Dev" />
Режым кантролюеўання увімкчва рэальную перакантроль і форматаванне за цену перыядзічнага атрыбутавання кожнай клавішы. Режым без кантролюеўання залічваецца легкім, калі патрэбна толькі фінальная значэнне. Магчымыя змешаныя формы — дзеякія польні кантролююцца, а дзеякія — ні — але ў аналізе ўскладненыя.
9. Перадача пропаў і калі зупыніцца
Перадача пропаў перадае даны через шары, якія іх толькі перадаюць далей. Перэменаванне называе багато файлаў. Контэкст дапамагае па тэме, аутантыкацыі чы регіону; Redux чы Zustand дапамагаюць, калі графікі стану становяцца складнымі. Нюанс: контэкст не ўжо безкоштовны — кожны спожывач перыядзічна атрыбутуецца, калі значэнне зміняецца — таму ён не являецца стандартам для кожнага спільнага польна. Перадача пропаў на два роўні часта ёсць яснейшая, чым стварэнне прадаўця контэксту для едынаковага значэння.
10. Калі краща вжыць useReducer замест useState?
Выбірайце useReducer, калі апдэты ведуцца за типам дзеяння, наступны стан залежыць ад паказванага стану спосабамі, якія не ўпростлены, або колькасць полей змінюецца разам:
function reducer(state, action) {
switch (action.type) {
case "increment": return { count: state.count + 1 };
case "reset": return { count: 0 };
default: return state;
}
}
const [state, dispatch] = useReducer(reducer, { count: 0 });
Это сваерадкая версія Redux унутрь компонента. Булевы параметры керуюцца за дапамою useState; складная логіка пераходу павінна знаходзіцца ў адным тэстуемым редюсеры. Вынесенне гэтай логіки з обробчыкаў запуску ў JSX таксама робіць тэсты на елементы простымі, без неабходнасці атрыбутавання всей структуры.
11. Паспяшыце useMemo vs useCallback, не проста цитуючы документацыю
Оба функцыі ухіляюцца ад зайвых вычысленняў между пераадрасаваннямі для разных форм данных:
useMemoзберагае ў кэшы вырачаную значэннеuseCallbackзберагае ў кэшы адказ на функцію
const sorted = useMemo(() => expensiveSort(list), [list]);
const handleClick = useCallback(() => doThing(id), [id]);
Ідэнтычнасць функцыі мае значэнне, таму што кожная перрадарбаванне стварае новы об’ект функцыі. Перадача новай функцыі ў дзецкі элемент memo усувае можлівасць мемаўзавання; useCallback захоўвае стабільнасць канкранта. Не трэба вжываць гэтыя хукі ў всіх месцах — мемаўзаванне мае свою цэну. Яго трэба викорыстоўваць толькі для складных або дорогих операцый чы для мемаўзавання дзецкіх элементаў. Нерэшаннае мемаўзаванне — частая прычына памылак у начаткавіках, яку спецыялісты любя выявляць пад час адбору.
12. React.memo ўжытковы — але лёгка ўсунуць
React.memo прыменшае колькісць перрадарбавання, калі пропсы є паверхнева ідэнтычныя. Новыя літералы об’ектаў чы масоў зарачунваюцца як разныя, нават калі ў іх ідэнтычны змест, таму викорыстанне { style: { color: 'red' } } робіць memo беспрактычным, якщо толькі родзіцы не стабілізуюць пропсы за дапамогою useMemo/useCallback. У іншым случае memo толькі збільшуе витраты на порэванне, не запобiegаючы выконанню задач дзецкім элементам.
13. Ключы як ідэнтыфікатор, а не проста паведамленне ў консолі
Ключы ёсць системай ідэнтыфікацыі у React межы перзапускамі компонентов. Некоректныя ключы выкарыстоўваюць неправільны элемент DOM для некоректных дадзеных: стан формы застаецца ў іншай строце, анімазіі запускаюцца на неправільным элементе, а useState у елементах ліста заставляе выкарыстоўваць значэння пярэднего элемента. Гэта выглядае як паспаленне стану; на самай працы гэта баг з ключамі. Деманстрацыя несправнага ліста з ключамі-індэксамі ў сандбоксе — адна з найшырэйшых способаў запам’ятаваць гэта правіла.
14. Кантэкст: правыя та неправыя задачы
Кантэкст дзеляеся значэннямі, якія патрэбны багатьм компонентам, без неабходнасці передачы ўсіх параметраў — автаналізаванный корыстнік, тэма, локацыя:
const ThemeContext = createContext();
<ThemeContext.Provider value={theme}>
<App />
</ThemeContext.Provider>
Гэта падходзіць слаба для высакачастых станоў (значэнняя формы на кожны натиск клавішы) у вялікай структуре, таму што кожны корыстнік апдэйтуецца пасля кожных змян без выбірчай падпіскі. Краща выбраць хранэнне з болей тонкімі падпіскамі для такага формата. Пераключэння тэм — класычны прыклад хорашага падходжання да контэксту; адносны положэнні курсора ў спільным редактары зазвычай такога падходжання не маюць.
15. Спраўленне жыцёвых циклаў класаў з эфектамі
Прыбліжнае спраўленне класаў:
componentDidMount→useEffect(..., [])componentDidUpdate→useEffect(..., [dep])componentWillUnmount→ чыстка эфектаў
Глыбэйшая змяненасць: ціклы жыцця працуюць па прынцыпу часу (з’яўленне/ацыі/знікненне); эфекты — па прынцыпе сінхронізацыі — трэба падтрымваць гармонію з гэтымі значэннямі, таму эфекты перзапускаюцца, калі змянююцыся залежнасці. Калі эфекты спрыяваюцца як методы ціклу жыцця, перакладзеныя лінія за лініёй, люди пачынаюць страждаць ад проблем з масавым спискам залежнасцяў.
16. Стан у пораўнанні з пропамі
Пропы — это толькі чытальныя даны з бацькага компонента. Стан — это даны, якія належачы компоненту і выклікаюць павтарную нарадку, калі яны змянююцца. Пропы налаштовуюць компонент ззаўні; стан — это тое, што компонент памятае пра сабе. label кнопкі ёсць пропам; тое, чы робіцца яна недзейным падчас виканання запиту, — это стан. Плутанне гэтых двух праграмаў ведае да анти-патэранаў, такіх як спробы змяніць пропы або падняць тымчасовыя флагі UI занадта высока.
17. Аднаходжэнне непатрэбных павтарных нарадакоў без здагадкаў
Звычныя прычыны: адзінкі, які перадаюць новыя літералы об’екта/масівы/функцыі, перарэндэраванне ўсіх корыстувачаў пад час змены контэксту, або тое, што стан знаходзіцца на вышэйшай паверсі, чым трэба. Не спадзяйцеся — выкорыстоўваючы інструмент Profiler у React DevTools, запісайце адно зі взаімадзейнаўанняў і паглядзеце, якія пропы зменіліся. Часта для вырашэння проблемы стан пераводзяць ніжча або дзеляюць компоненты, каб дорогія паддрэсі не адбываліся праз дешавыя апдэйты, а не спачатку накрыць усё useMemo. Інструменты профілювання ператвараюць вясковасць «здаецца, што ўсё медленна» на конкрэтныя пояснення ўзгаліва/пропаў, якія можна вырашыць.
18. SSR у порэвананні з CSR
CSR адрасуе тонкі HTML-шэлак плюс код на JS; прыстрой для перагляду стварае сторанку пасля завантажэння — шырока адпаведна, але памедзе ў стварэнні рэальнае версія сторанкі, історычна слабейша з точка зору SEO пакуль не запрацюе JS. SSR адрасуе HTML за кожны запит, а пасля гідратацыя — праз прыўязку слухачаў; гэта дае лепшыя показнікі першага адрасавання сторанкі і SEO, але выклікае большую навантажэнна на сервер. Next.js і падобныя фреймворкі дадаюць можлівасць статычнага генеравання та стрімінгу, але основны компроміс застаецца межу TTFB/SEO і вартасцю ўтратаў сервера ўсьведамлення. Заява «SSR завжды лепш» без указвання гэтага компроміса ёстся слабым адказам у інтэрв’ю.
19. Несувяранасці гідратацыі і прычыны ўсунення іх
Функцыя Hydration прыўязвае React да HTML сервера, не выкарыстоўваючы маркап для збрасці. Несувямства выступаюць, калі HTML сервера не збігаецца з першым атрыбутаваннем на кліянце: Date.now() або Math.random() у процесе атрыбутавання, перагляд window, які разніцяўся на сервере, або дадатковыя элементы, якія вставляюцца. React сильна паветарае і часта ператрыбутаввае на кліянце, каб восстановіць стан — гэта додатковая праца плюс видны момент з некоректным кантэнтам. Звычайны спосаб прыменшэння гэтых проблем — захаванне API, якія дзейнаць толькі ў браузеры, за дапамою useEffect або спецыяльных компонентаў.
20. Чаму React абгортае натыўныя з’явы ў SyntheticEvent
У React клас SyntheticEvent нормалізуе особлівасці розных прыгравароў (чаму onChange працуюць адносова аднакава), і ранейшыя версіі викорыстоўвалі дэлегаванне адбуваюцца на роўні корня, замест аднае натыўная прыемнік на кожны вузел. У React 17+ дэлегаванне адбываецца на контейнер корня прыкладнення, а не на document, але ідея застаўся тая ж. Ранейшы метод пулінга викорыстоўвался для перадзяйснення аб’ектаў змагання, ўнаследкі чыго асінхронны доступ могаў вернуць null; пулінг зняты з версій React 17, але ведаць пра шар межу змагання прыгравара і прыемніка все ўсё паказвае глęбіну структуры. Адзначэнне таго, што e.nativeEvent все ўсё існуе пад спаднім шаром, паказвае, што вы розумееце, што абстракцыя ёсць толькі обгорткай, а не заменой для модэлю змагання DOM.
Што на самай працоўскай спышцы дзеясно ценіцца
Хорашыя адказы на запытаннія паводле якога ўскладнення, прычыны гэтага і як вы моглі б дапамогчы колеге — а не проста запам’ятаваная вялічына. Запытальнікі менш заўсёды заінтэресаваныя ў тым, чы можаце вы дастаць вялічыну useEffect, а больш — у тым, чы не сталіся у вас проблемы з застарэлымі клоузарамі, відсутнасцю чысткі або памылкамі ў залежнасцях, і чы можаце вы поясніць прычыны. Перад запытаннем перадаце гэтыя багі ў сандбоксе; доказы рэальных проблем паказваюць ваша разуменне. Вялічыны дапамагают перазйсці першую хвіліну; адносы выгод і історыі неудач прыводзяць да продажнага размовы.
Зберагачыце короткі персональны справак з працэвыканых вамі багоў — застарелыя эфекты, некоректныя клавішы, несувараснасці ў гідратацыі — і практыкуйцеся адказваць на запытанні пра кожны з іх за менш чаму за мінуту. Такая падготовка краща, чым запамятаванне сінтаксу API за ночь, і яна дапамагае даваць конкрэтныя прыклады, калі спакавальнік просіць практычны прыклад з вашай роботы. Супаўнавайце кожны прыклад з адпаведным рашэнням, каб адказ заканчваўся ацэнкай, а не толькі описам проблемы. Саме гэты крок адразняе тых, хто проста «чытае дакументацыю», ад тых, хто можа кераваць цім стэкам пад тыччую натоўпу.