Реакция: useEffect против useMemo против useState

Я безуспешно пытался найти краткий ответ на этот вопрос в Интернете.

Верно ли следующее в отношении различий между useEffect, useMemo и useState?

  • ОбеuseState и useMemo запомнят значение при рендеринге. Разница в том, что:
    • useMemo не вызывает повторный рендеринг, а useState вызывает
    • useMemo запускается только тогда, когда его зависимости (если они есть) изменились, в то время как setSomeState (второй элемент массива, возвращаемый useState) не имеет такого массива зависимостей
  • ОбеuseMemo и useEffect запускаются только при изменении их зависимостей (если они есть). Разница в том, что:
    • useEffect запускает после, происходит рендеринг, а useMemo запускает до

Какие-либо другие ключевые отличия, которые я пропустил?

ты это читал? overreacted.io/a-complete-guide-to-useeffect

azium 28.05.2019 20:02
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
24
1
11 855
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Ваши пункты в основном верны, небольшое уточнение:

использование состояния вызывает повторную визуализацию при вызове метода setState (возвращается второй элемент в массиве). Он не имеет никаких зависимостей, таких как useMemo или useEffect.

useMemo пересчитывает значение только в том случае, если элементы в его массиве зависимостей изменяются (если зависимостей нет, т.е. массив пуст, он будет пересчитываться только один раз). Если массив не указан, он будет пересчитываться при каждом рендеринге. Вызов функции не вызывает повторного рендеринга. Также он запускает в течение при рендеринге компонента, а не раньше.

использованиеЭффект вызывается после при каждом рендеринге, если элементы в его массиве зависимостей изменились или массив пропущен. Если массив пуст, он будет запущен только один раз при начальном монтировании (и размонтирован, если вы вернете функцию очистки).

Вы всегда можете проверить Справочник API хуков, который, на мой взгляд, является довольно надежной документацией.

Что меня интересует, так это основная разница в объявлении констант: ts const foo = useMemo(factoryForCreatingConstant, []); // vs const [bar] = useState(factoryForCreatingConstant); Оба кажутся функционально эквивалентными.

bfricka 26.08.2019 22:04

Вы правы, если вы используете это так, они кажутся функционально эквивалентными. useMemo пересчитывает только в случае изменения массива зависимостей, чего в данном случае никогда не происходит (поскольку массив пуст). Я отредактировал свой пост, чтобы учесть разницу между передачей массива зависимостей и передачей пустого массива. С useState вы получаете метод setState в качестве второго элемента массива и можете вручную вызвать повторную визуализацию, в то время как useMemo будет пересчитывать только в том случае, если его зависимости изменились.

saltenhub 28.08.2019 10:17

Между прочим, мне было очень любопытно определить константы, инициализируемые компонентами, поэтому я добавил этот комментарий. Я закончил размещение вопроса, если вы заинтересованы в обсуждении.

bfricka 30.08.2019 21:55

@saltenhub Я до сих пор не могу понять, чем useMemo лучше, когда дело доходит до тяжелых вычислений, чем useEffect, если они оба работают только при изменении зависимостей.

Noamaan Mulla 22.09.2021 19:26

@NoamaanMulla useMemo и useEffect имеют разные варианты использования (первый запускается во время рендеринга, второй — после рендеринга — как объяснялось выше). В некоторых случаях они дают очень похожий/одинаковый результат (см. этот ответ stackoverflow.com/a/68201925/10320683)

saltenhub 20.10.2021 15:46
  • Возвращаемое значение useEffect(callback, [dependency]) равно void и выполняется после render().
  • Возвращаемое значение useMemo(callback, [dependency]) НЕ void, а запомненное значение, и оно выполняется ВО ВРЕМЯ render().

useEffect() может дать ту же оптимизацию, что и useMemo(), при следующих обстоятельствах:

  • Переменная состояния, используемая в дорогостоящих вычислениях (например, count1), является единственной зависимостью useEffect.
  • Когда мы не возражаем хранить дорого вычисляемое значение в переменной состояния.
const [count1, setCount1] = useState(0);
const [expensiveValue, setExpensiveValue] = useState(null);
useEffect(() => {
    console.info("I am performing expensive computation");
    setExpensiveValue(((count1 * 1000) % 12.4) * 51000 - 4000);
  }, [count1]);   
  • Разница лишь в том, что useEffect() делает дорогостоящее значение доступным после render(), а useMemo() делает значение доступным во время render().
  • В большинстве случаев это не имеет значения, потому что, если это значение было рассчитано для рендеринга в пользовательском интерфейсе, useEffect() и useMemo() оба сделают значение доступным до того, как браузер завершит рисование.

useMemo Используется для запоминания вычислений/значений, которые принадлежат компоненту, но не обязательно его состоянию, например. проверки, методы, которые полагаются на компонент и должны возвращать значение;

  const validEmail = React.useMemo(() => validateEmail(email), [email])
  /* Now use 'validEmail' variable across the component, 
     whereas 'useEffect' return value is void and only used for unmounting duties, 
     like unsubscribing from subscription e.g. removeInterval*/

из документов:

Remember that the function passed to useMemo runs during rendering. Don’t do anything there that you wouldn’t normally do while rendering. For example, side effects belong in useEffect, not useMemo.


useEffectПобочные эффекты:

Mutations, subscriptions, timers, logging, and other side effects

setState's setTimeout' setInterval' ref назначения, вызовы API или все, что не выполняет тяжелых вычислений, больше относится сюда.

Также помните, что за оптимизацию приходится платить, поэтому React предлагает использовать useMemo только тогда, когда необходима мемоизация/оптимизация, а в остальных случаях полагаться на useEffect, когда это необходимо:

You may rely on useMemo as a performance optimization, not as a semantic guarantee.

In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo — and then add it to optimize performance.


[state, setState] = useState()то есть для обновления данной переменной состояния, которая остается стабильной во время повторного рендеринга, и вызов прикрепленного к ней setState запускает повторный рендеринг. Назначение этого крючка не очень связано с двумя вышеупомянутыми крючками.

Другие вопросы по теме