У меня есть следующий функциональный компонент React:

const MyComp = (props) => {
  const [dict, setDict] = useState({});

  const myFunc = () => {
    [1, 2, 3].forEach(x => {
      fetch('something' + x)
        .then(res => res.json())
        .then(res => {
          setDict({...dict, [x]: res.y}); // <--------   PROBLEMATIC HERE
        })
    });
  }
}

Похоже, что React предварительно оптимизирует это, поэтому все мои вызовы setDict собраны в один. Это означает, что dict имеет только один произвольный результат из нескольких обратных вызовов. Как я могу этого добиться?

1
7ball 10 Фев 2021 в 09:27

2 ответа

Лучший ответ

Проблема

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

Решение

Используйте обновление функционального состояния. Разница здесь в том, что функциональное состояние обновляет обновления из предыдущего состояния, а не состояния из предыдущего цикла рендеринга. Требуется лишь небольшая настройка с setDict({...dict, [x]: res.y}) на setDict(dict => ({...dict, [x]: res.y})).

const MyComp = (props) => {
  const [dict, setDict] = useState({});

  const myFunc = () => {
    [1, 2, 3].forEach(x => {
      fetch('something' + x)
        .then(res => res.json())
        .then(res => {
          setDict(dict => ({...dict, [x]: res.y}));
        })
    });
  }
}
0
Drew Reese 10 Фев 2021 в 06:43

setState предоставляет текущее значение вашего состояния в первом аргументе обратного вызова

Поэтому используйте значение dict из аргумента обратного вызова, а не значение состояния dict

const MyComp = (props) => {
const [dict, setDict] = useState({});

const myFunc = () => {
  [1, 2, 3].forEach(x => {
    fetch('something' + x)
      .then(res => res.json())
      .then(res => {
        setDict((dict) => {...dict, [x]: res.y}); // <--------   PROBLEMATIC HERE
      })
  });
}
0
Sangam Rajpara 10 Фев 2021 в 06:45
66131916