изменение значения useContext при повторной визуализации

Итак, у меня есть компонент, который выглядит примерно так:

const App = () => {
  const someContextValue = useSomeContext();  //custom hook that calls useContext

  useEffect(() => {
    someContextValue()
  }, [someContextValue]);

  return <div />
}

Каждый раз, когда компонент выполняет повторную визуализацию, запускается useEffect, даже если someContextValue на самом деле не изменился.

Я обошел это, используя useMemo, например

const someContextValue = useMemo(useSomeContext, [useSomeContext])

Теперь someContextValue не меняется при повторной визуализации. Но мне кажется, что это не совсем так. Как правильно это сделать?


person Sreya Rajendran    schedule 11.05.2020    source источник
comment
Значение контекста ИЗМЕНИЛОСЬ. Поскольку значение определяется внутри компонента, а компонент является функцией. Когда функция запускается, значения, которые определены внутри нее, определяются. Когда вы вызываете useSomeContext(), вы создаете новый объект, и это происходит каждый раз при рендеринге компонента. Это не то же самое, что значение состояния, где значение состояния не переопределяется, хук useState поддерживает один и тот же экземпляр значения, поэтому он не воссоздается каждый раз.   -  person JMadelaine    schedule 11.05.2020
comment
Я добавил свой комментарий как более подробный ответ.   -  person JMadelaine    schedule 11.05.2020


Ответы (1)


Если вы возвращаете объект {} или массив [] из контекста, то значение контекста ИЗМЕНИЛОСЬ.

Переменная someContextValue определяется внутри компонента.

Компонент - это функция, и когда функция запускается, значения, определенные внутри нее, определяются. Если, например, ваш контекст возвращает объект, содержащий значения состояния, то этот объект является экземпляром, отличным от экземпляра из предыдущего рендеринга, и ваш useEffect запускается из-за этого.

useEffect будет сравнивать ссылочные типы по их экземпляру, а не по значениям внутри них.

Когда вы вызываете useSomeContext(), вы создаете новый объект, и это происходит каждый раз при рендеринге компонента.

Это не то же самое, что значение состояния из useState, где значение состояния не переопределяется. Хук useState поддерживает один и тот же экземпляр значения, поэтому он не создается заново каждый раз, и useEffect видит, что значение состояния является одним и тем же экземпляром.

Вот почему при использовании контекста вы должны деструктурировать объект контекста и ссылаться на значения внутри объекта, которые являются либо значениями состояния, переданными из ловушки useState внутри контекст или значение, определенное внутри контекста, которое не переопределяется при повторном рендеринге вашего потребляющего компонента (поскольку в этом случае контекст не повторно рендерится):

const { someStateValue } = useSomeContext()

useEffect(() => {
  someStateValue()
}, [someStateValue]);
person JMadelaine    schedule 11.05.2020