TGViewer
dev.easy dev.easy @dev_easy · 135 subscribers
Post #19 677
⚛️ неочевидный react

Похоже, далеко не все понимают как работает React, в частности: контекст, рендер, как всплывают события и почему происходят ремаунты, казалось бы в тех местах, где их не должно быть. Я конечно не претендую на реакт-эксперта, но хотел бы прояснить кое-какие моменты, которые не описаны в доке, или упоминаются как-то вскользь. Будет много ссылок на демки где можно поиграться, посмотреть логи и подробнее разобраться.

- Начнем с самого простого - контекста. Контекст нужен что бы доставить данные вглубь React дерева, при это избегая props-drillingа, пробрасывания данных через кучу родителей к дочерним. В целом в доке все отлично расписано, но многие не обращают внимание на один важный момент: все потребители контекста, неважно, это Context.Consumer или React.useContext(Context) , будут перерисовываться (т.е. вызван render метод, а не обновлен DOM) каждый раз когда значение контекста меняется. Это значит что использовать объекты, без предварительного кэширования, в контексте - плохая идея, т.к. все потребители будут перерисовываться на каждый рендер провайдера, даже если данные в этом объекте никогда не меняются.

<Context.Provider value={{ value: 20 }}>{children}</Context.Provider>

https://codesandbox.io/s/object-in-the-context-nh1ud?file=/src/App.tsx в этом примере на каждый рендер провайдера создается новый объект, что вызывает перерасчет всех потребителей, в больших приложениях это может привести к большому даунгрейду перфа. Фикситься достаточно просто, использованием useMemo или useRef, в зависимости от того, меняются ли значения в объекте.

- Как я понял, многие предполагают что компонент монтируются (или по крайней мере его рендер вызывается) в момент создание элемента const child = <Child /> , даже если элемент не был использован в ретурне рендера родителя. На самом деле это не так, компонент не монтируется и даже его рендер не вызывается, если элемента этого компонента нет в React дереве, другими словами если компонент не был использован в ретурне рендера родителя. Отсюда вытекает еще одна неочевидность: компонент монтируются столько раз, сколько раз его элемент появился в React дереве.

const child = <Child name="renderChild" />;
const unusedChild = <Child name="unusedChild" />;

return (
<>
{child}
{child}
{child}

{false && unusedChild}
</>
)

https://codesandbox.io/s/react-render-8zm5d?file=/src/App.tsx:1059-1070 в примере выше Child с названием renderChild монтируются 3 раза, т.к. 3 элемента используется в дереве, а вот unusedChild вообще не монтируются да и рендер для него тоже не вызовется, поскольку его нет в дереве. Все тоже касается и последующих ререндеров, но здесь есть 2 НО, когда ререндера может не произойти:
1) компонент использует React.memo - пропсы не поменялись, ререндер не произошел
2) новый элемент не был создан в момент ререндера родителя - это можно сделать различными способами, в примере по ссылке это делается через создание элементов за пределами рендер метода. Но того же эффекта можно добиться положив элемент в useRef или useMemo . Чет мне кажется, что работает оно так-же как и React.memo только без дополнительных проверок пропсов в момент рендера, а просто сравнивается сслыка элемента - я не проверял в сорцах, просто предположение.

Продолжение в первом коменте...
Читать в ноушен: https://bit.ly/3jwrFYY

#react
  • 👍 2
More from @dev_easy
  1. Nov 12, 2021🦾 local env на стиройдах Как я уже упоминал несколько раз, весь наш бэкенд построен на ми…
  2. Oct 14, 2021🚐 лайфхаки ревью В стартапе где я работаю нет тестировщиков, от слова вообще. Мы, конечно…
  3. Oct 6, 2021🔫 самое коварное CSS свойство Пару недель назад наш дизайнер завел ишью, мол у него в хро…
  4. Sep 23, 2021🗽vite - будущее уже здесь Сегодня знаменательный день, мы переехали с webpack5 на vite. З…
  5. Sep 16, 2021🎃 react-redux и connect-хелл На днях разговаривая с коллегами и друзьями осознал что дале…
  6. Aug 27, 2021🎹 Массивы и Таплы В TS/JS массивы можно разделить на 2 типа, обычные массивы и таплы (tup…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →