#javascript #reactjs #react-hooks
#javascript #reactjs #реагирующие перехваты
Вопрос:
Компоненты класса
В компонентах класса React нам говорят, что это setState
всегда приводит к повторному рендерингу, независимо от того, действительно ли состояние изменилось на новое значение. По сути, компонент будет повторно рендериться, когда состояние обновится до того же значения, которое было раньше.
Документы (ссылка на setState API):
setState() всегда приведет к повторному рендерингу, если shouldComponentUpdate() не возвращает false .
Перехваты (функциональные компоненты)
Однако с помощью перехватов в документах указано, что обновление состояния до значения, идентичного предыдущему состоянию, не приведет к повторному рендерингу (дочерних компонентов):
Документы (ссылка на API useState):
Отказ от обновления состояния
Если вы обновите перехват состояния до того же значения, что и текущее состояние, React завершит работу без рендеринга дочерних элементов или запуска эффектов. (React использует Object.is алгоритм сравнения.)
Тесно связанные вопросы
- Правильно ли, что
this.setState
компоненты в классе всегда вызывают повторный рендеринг, даже когда новоеstate
значение идентично предыдущему? - Правильно ли, что в функциональных компонентах с помощью перехватов
setState
fromuseState
вызывает повторный рендеринг, только еслиstate
значение отличается от предыдущего значения? - Является ли настройка
state
с помощьюthis.setState
внутриrender
метода компонента класса такой же, как настройкаstate
внутри тела функции функционального компонента с помощью перехватов? - Верно ли следующее?
- В компоненте класса, если мы установим
state
вrender
методе, будет происходить бесконечный цикл. Это потому, что компоненту класса все равно, что новыйstate
совпадает с предыдущимstate
. Он просто продолжает повторный рендеринг при каждомthis.setState
. - Однако в функциональном компоненте с перехватами настройка внутри тела функции (которая выполняется при повторном рендеринге аналогично
state
методу вrender
компонентах класса) не была бы проблемой, потому что функциональный компонент просто прекращает повторный рендеринг, когда видит, что он идентичен предыдущемуstate
. ……………………state
- В компоненте класса, если мы установим
Комментарии:
1.
we are told that setState always causes a re-render
я не уверен в этом. Если вы возвращаете nullthis.setState(() => null)
, он ничего не рендерит повторно.2. Что именно вы подразумеваете под вызовом 3? setState?
3. @estus Да, прояснил OP.
Ответ №1:
Правильно ли, что this.setState в компонентах класса всегда вызывает повторный рендеринг, даже когда новое значение состояния идентично предыдущему?
Если вы задаете допустимое значение, отличное от возвращаемого null в setState, повторный рендеринг всегда будет запускаться react в компоненте класса, если ваш компонент не является PureComponent или вы не реализуете shouldComponentUpdate
Правильно ли, что в функциональных компонентах с перехватами setState из useState вызывает повторный рендеринг, только если значение состояния отличается от предыдущего значения?
Для функционального компонента, использующего useState
перехват, установщик, если он вызван с тем же состоянием, не запустит повторный рендеринг. Однако в редких случаях, если установщик вызывается немедленно, это приводит к двум рендерингам вместо одного
Устанавливает ли state с помощью this.setState внутри метода рендеринга компонента класса то же самое, что устанавливает state внутри тела функции функционального компонента с помощью перехватов?
Технически да, установка состояния непосредственно в методе render приведет к тому, что функция запустит повторный рендеринг в случае, если компонент класса вызывает бесконечный цикл, что имеет место для функциональных компонентов при условии, что значения состояния отличаются. Независимо от этого, это все равно вызовет проблему, поскольку любое другое обновление состояния будет возвращено обратно из-за того, что функциональный компонент напрямую вызывает обновление состояния
В компоненте класса, если мы установим состояние в методе render, возникнет бесконечный цикл. Это происходит потому, что компоненту класса все равно, что новое состояние совпадает с предыдущим состоянием. Он просто продолжает повторный рендеринг для каждого this.setState.
Да, следовательно, рекомендуется не вызывать setState непосредственно при рендеринге
Однако в функциональном компоненте с помощью перехватов установка состояния внутри тела функции (которое выполняется при повторном рендеринге аналогично методу рендеринга в компонентах класса) не будет проблемой, потому что функциональный компонент просто завершает повторный рендеринг, когда видит, что состояние идентично предыдущему состоянию.
Не на 100% верно, поскольку вы можете инициировать обновление состояния, используя предыдущее значение, так что предыдущее и текущее значения не совпадают.Например
setCount(count => count 1);
В таком случае ваш компонент все равно попадет в бесконечный цикл
Комментарии:
1. Если вы реализуете shouldComponentUpdate для возврата false, если состояние или реквизиты не изменились, то ваш компонент не будет повторно рендерить
2. @Magnus, да, опечатка с моей стороны. Обновлен ответ
3. Спасибо, глубоко признателен. Где вы находите всю эту информацию? В официальных документах очень мало информации о том, когда и почему происходят повторные рендеринги. Они действительно должны создать страницу по этой теме…
4. Я так или иначе тестировал вышеупомянутые сценарии с течением времени
5. @Magnus, да, ты прав. эффекты представляют собой дополнительную логику к функциональному компоненту, которого нет в render for class component
Ответ №2:
Это не прямой ответ на OP, но связанный и, возможно, полезный для некоторых людей, которые новички в React и / или хуксах и борются с их побочным эффектом и временем рендеринга.
Поскольку здесь еще не упоминалось: в функциональных компонентах вместо использования вышеупомянутой (см. Комментарии к принятому ответу) ShouldComponentUpdate()
функции, которая предназначена только для компонентов, основанных на классе, вы бы использовали useEffect()
перехват. С его помощью вы можете указывать своему компоненту, когда запускать побочные эффекты И при каких условиях, например, при изменении определенных зависимостей.
В этом примере из документации React функция будет выполнена только при props.source
изменении.
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);