React useEffect не перезагружает мой компонент после обновления состояния - PullRequest
1 голос
/ 28 мая 2020

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

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

1. Что делает мой код:

У меня есть простой useEffect хук, который я хочу вызвать при изменении props rank. В ловушке я вызываю метод toggleNodeByRank(), используя .then, и обновляю свое состояние с именем data после выполнения метода.

2. Что происходит:

На данный момент (почти) все работает нормально, а во втором console.log('===StateUpdated===', chartData); я вижу, что мое состояние имеет правильное обновленное значение.

Единственная проблема в том, что мой компонент не перезагружается, и если я повторю действие, обновляющее реквизиты rank, я увижу изменения.

Я видел несколько ответов, в которых говорилось, что deps (rank здесь) не были хорошими, я попытался добавить chartData также в deps ([rank, chartData]), но проблема осталась той же ...

Может быть, кто-то может мне помочь вот этот ?

useEffect(() => 
  console.log('===PreviousState===', chartData);

  toggleNodeByRank(chartData, rank).then((data) => setChartData(data));

  console.log('===StateUpdated===', chartData);

}, [rank]);

3. Изменить

Вот функция toggleNodeByRank (), так как это код моей компании, я предпочитаю не раскрывать слишком много информации, надеюсь, это поможет вам, ребята ..

  const toggleNodeByRank = async (node, rank) => {
    if (node && node.data) {
      // await update node.children depending on node.rank
      // - If I want to toggle the node :
      // I am saving the node.children in a state object (key = node.id, 
      // value = node.children) and I reset the node.children value to [ ]
      // - If I don't want to toggle the node :
      // I don't do anything and juste render
      // update another state to save the node.children data if needed.
      return node;
    }
  };

Ответы [ 2 ]

2 голосов
/ 28 мая 2020

Поскольку вы изменяете исходный элемент узла на месте вместо того, чтобы обновлять его неизменным образом, setChartData не запускает повторную визуализацию, поскольку реакция проверяет, действительно ли значение, переданное в средство обновления состояния, изменилось с предыдущего значения или нет, и поскольку ссылка такая же, он считает, что ничего не изменилось

В соответствии с принципами React вы никогда не должны изменять значения состояния, вместо этого обновляйте их неизменным способом.

Если вы можете обновить состояние неизменяемым образом, сделайте это в toggleNodeByRank

Однако вы все равно можете обойти эту проблему, неглубоко клонировав узел, например

const toggleNodeByRank = async (nodeArg, rank) => {
    const node = {...nodeArg};
    if (node && node.data) {
      return node;
    }
  };

После выполнения вышеуказанного изменения это вызовет повторное -rerender, но вы должны знать, что это не лучший способ

0 голосов
/ 28 мая 2020

У вас проблемы с пониманием обещаний, в вашем коде эти 2 console.log будут выводить то же значение, потому что (data) => setChartData(data) - это ведьма обратного вызова, которая будет вызвана после выполнения toggleNodeByRank. В основном ваш код выполняется следующим образом:

1) console.log ('=== PreviousState ===', chartData);

2) toggleNodeByRank (chartData, rank); // здесь вы просто отправляете запрос

3) console.log ('=== StateUpdated ===', chartData);

4) (data) => setChartData (data)

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

...