Я безуспешно пытался найти краткий ответ на этот вопрос в Интернете.
Верно ли следующее в отношении различий между useEffect
, useMemo
и useState
?
useState
и useMemo
запомнят значение при рендеринге. Разница в том, что:
useMemo
не вызывает повторный рендеринг, а useState
вызываетuseMemo
запускается только тогда, когда его зависимости (если они есть) изменились, в то время как setSomeState
(второй элемент массива, возвращаемый useState
) не имеет такого массива зависимостейuseMemo
и useEffect
запускаются только при изменении их зависимостей (если они есть). Разница в том, что:
useEffect
запускает после, происходит рендеринг, а useMemo
запускает доКакие-либо другие ключевые отличия, которые я пропустил?
Ваши пункты в основном верны, небольшое уточнение:
использование состояния вызывает повторную визуализацию при вызове метода setState (возвращается второй элемент в массиве). Он не имеет никаких зависимостей, таких как useMemo или useEffect.
useMemo пересчитывает значение только в том случае, если элементы в его массиве зависимостей изменяются (если зависимостей нет, т.е. массив пуст, он будет пересчитываться только один раз). Если массив не указан, он будет пересчитываться при каждом рендеринге. Вызов функции не вызывает повторного рендеринга. Также он запускает в течение при рендеринге компонента, а не раньше.
использованиеЭффект вызывается после при каждом рендеринге, если элементы в его массиве зависимостей изменились или массив пропущен. Если массив пуст, он будет запущен только один раз при начальном монтировании (и размонтирован, если вы вернете функцию очистки).
Вы всегда можете проверить Справочник API хуков, который, на мой взгляд, является довольно надежной документацией.
Что меня интересует, так это основная разница в объявлении констант: ts const foo = useMemo(factoryForCreatingConstant, []); // vs const [bar] = useState(factoryForCreatingConstant);
Оба кажутся функционально эквивалентными.
Вы правы, если вы используете это так, они кажутся функционально эквивалентными. useMemo
пересчитывает только в случае изменения массива зависимостей, чего в данном случае никогда не происходит (поскольку массив пуст). Я отредактировал свой пост, чтобы учесть разницу между передачей массива зависимостей и передачей пустого массива. С useState
вы получаете метод setState
в качестве второго элемента массива и можете вручную вызвать повторную визуализацию, в то время как useMemo будет пересчитывать только в том случае, если его зависимости изменились.
Между прочим, мне было очень любопытно определить константы, инициализируемые компонентами, поэтому я добавил этот комментарий. Я закончил размещение вопроса, если вы заинтересованы в обсуждении.
@saltenhub Я до сих пор не могу понять, чем useMemo
лучше, когда дело доходит до тяжелых вычислений, чем useEffect
, если они оба работают только при изменении зависимостей.
@NoamaanMulla useMemo
и useEffect
имеют разные варианты использования (первый запускается во время рендеринга, второй — после рендеринга — как объяснялось выше). В некоторых случаях они дают очень похожий/одинаковый результат (см. этот ответ stackoverflow.com/a/68201925/10320683)
useEffect(callback, [dependency])
равно void
и выполняется после render()
.useMemo(callback, [dependency])
НЕ void
, а запомненное значение, и оно выполняется ВО ВРЕМЯ render()
.useEffect()
может дать ту же оптимизацию, что и useMemo(), при следующих обстоятельствах:
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]);
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
запускает повторный рендеринг. Назначение этого крючка не очень связано с двумя вышеупомянутыми крючками.
ты это читал? overreacted.io/a-complete-guide-to-useeffect