React useEffect, включая отсутствующую зависимость, сломает его - PullRequest
1 голос
/ 26 мая 2020

Я работаю над приложением React с некоторыми useEffect хуками. Допустим, у меня есть следующий код:

import React, { useState, useEffect } from 'react';

export default () => {
  const [fooArr, setFooArr] = useState([]);
  const [barObj, setBarObj] = useState({});

  return <h1>{barObj.name + " " + barObj.status}</h1>
}

Но теперь проблема. fooArr изменяется где-то еще, и я хочу обновить barObj при изменении fooArr. Я сделал это, как показано ниже:

import React, { useState, useEffect } from 'react';

export default () => {
  const [fooArr, setFooArr] = useState([]);
  const [barObj, setBarObj] = useState({});

  // >>> some fetching and setting of 'fooArr' here <<<

  useEffect(() => {
    setBarObj(barObj => {
      let _barObj = { ...barObj };
      _barObj.status = fooArr[1];
      return _barObj;
    })
  }, [fooArr]);

  return <h1>{barObj.name + " " + barObj.status}</h1>
}

Однако это дает мне следующую ошибку React Hook useEffect has a missing dependency: 'barObj' and 'setBarObj'. Either include it or remove the dependency array. Я точно знаю, что это означает , но когда я включаю его, я получаю бесконечный повторный рендеринг l oop, потому что он продолжает обновляться . Теперь у меня есть // eslint-disable-line рядом с массивом зависимостей, чтобы игнорировать это. Но я чувствую, что этого никогда не следует делать.

Как мне с этим справиться? Я бы хотел не получать сообщение об ошибке, но также не иметь бесконечного повторного рендеринга l oop ..

Пример с дополнительным кодом, который похож на мой код:

useEffect(() => {
  setBarObj(prevBarObj => {
    let _barObj = { ...prevBarObj };
    if(_barObj.status.includes('hello') {
      _barObj.status += "world"
    } else {
      _barObj.status = "other"
    }
    return _barObj;
  })
}, [fooArr])

Ответы [ 2 ]

3 голосов
/ 26 мая 2020

Я думаю, что отображается предупреждение об отсутствующей зависимости, потому что вы скрываете barObj от состояния. Попробуйте использовать другое имя аргумента и избегайте копирования объекта:

useEffect(() => {
    setBarObj(bar => {
      return {...bar, status: fooArr[1]};
    })
  }, [fooArr]);
1 голос
/ 26 мая 2020

Это должно работать нормально:

useEffect(() => {
  setBarObj(barObj => ({
    ...barObj,
    status: fooArr[1]
  })
}, [fooArr]);

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


Согласно вашему комментарию, вы можете сделать следующее:

useEffect(() => {
  if (barObj.status === 'hello') return
  setBarObj(barObj => ({
    ...barObj,
    status: fooArr[1]
  })
}, [fooArr]);

С обновленным запросом вы можете использовать как:

useEffect(() => {
  setBarObj(barObj => {
    const updatedStatus = barObj.status === 'hello' ? (barObj.status + 'world') : fooArr[1]
    return {
    ...barObj,
    status: updatedStatus
  }
}, [fooArr]);
...