Сравнение эталонных значений React Hooks - PullRequest
2 голосов
/ 25 мая 2020

всем! Представьте, у меня есть компонент SomeComponent. Каждый раз, когда изменяется значение 'b', срабатывает useEffect, несмотря на то, что 'b не входит в его зависимости

const SomeComponent = () => {
  const a = [1, 2, 3] //just an example of dependency. In real life it will be a changing value
  const b = useSelector(someValueSelector)

  useEffect(() => {
    //do some staff
  }, [a])
}

Есть ли способ сохранить ссылку на массив' a 'внутри SomeComponent? Единственный известный мне способ - создать компонент-оболочку и передать

a = useMemo(() => [1, 2, 3], [])

в качестве реквизита в

<SomeComponent a={a} />

Ответы [ 2 ]

1 голос
/ 25 мая 2020

Проблема здесь в том, что при каждом повторном рендеринге ссылка на a изменяется, и, следовательно, useEffect запускается снова

Вы можете использовать useMemo внутри SomeComponent, чтобы присвоить мемоизированное значение a

const SomeComponent = () => {
  const a = useMemo(() => [1, 2, 3], []); 
  const b = useSelector(someValueSelector)

  useEffect(() => {
    //do some staff
  }, [a])
}
0 голосов
/ 25 мая 2020

Как вы, возможно, догадались, но, чтобы быть ясным для будущих читателей, это связано с равенством объектов в JavaScript. Поскольку объекты сравниваются по ссылке, {} === {} оценивается как false.

В зависимости от вашего варианта использования это можно обойти следующими способами:

  1. Если значения являются статическими c и не зависят от свойств, определите a в той же области, что и компонент. Это избавляет от необходимости объявлять его как зависимость для подпрограммы useEffect:

    const a = [1, 2, 3]
    const SomeComponent = () => {
      useEffect(() => {
        // do something with `a`
      }, [])
    }
    
  2. Если значение - динамическое c, но изменения не должны вызывать повторный рендеринг компонента, используйте исх. Изменение значения ref не будет побуждать React к повторной визуализации компонента, и тот же объект будет возвращаться из useRef() при каждой визуализации:
    const SomeComponent = () => {
      const ref = useRef([1, 2, 3])
      useEffect(() => {
        // do something with ref.current
      }, [ref])
    }
    
  3. Наконец, если значение a равно Dynami c или в зависимости от свойств, которые могут меняться со временем, используйте useMemo. Имейте в виду, что useMemo не является гарантией semanti c - React может выбрать извлечение сохраненных значений для освобождения памяти, и поэтому его следует использовать только для оптимизации производительности:
    const SomeComponent = () => {
      const a = useMemo(() => [1, 2, 3], [])
      useEffect(() => {
        // do something with a
      }, [a])
    }
    
...