Как выполнить пакетную обработку вызовов React setState () внутри функции asyn c? - PullRequest
1 голос
/ 20 января 2020

Поэтому я столкнулся с проблемой, когда React не объединяет несколько вызовов setState () внутри асинхронной c функции (обычно React делает это автоматически вне асинхронной c функции). Это означает, что когда мой код выполняется, множественные последовательные вызовы setState () конфликтуют друг с другом, первый setState () вызывает обновление компонента, а второй setState () происходит до того, как компонент успел перемонтировать, и я получаю ошибку Msgstr "Невозможно выполнить обновление состояния React для неустановленного компонента". Я провел некоторое исследование и обнаружил, что это ожидаемое поведение, но я ничего не нашел о том, как решить проблему.

Вот пример кода (не запускается) просто для визуализации того, что я пытаюсь сказать. В этом случае строки setData (response.data); и setLoading (false); конфликт и причина ошибки.

Мне нужен какой-то способ сделать два вызова atomi c.

import React, { useState } from "react";
import Button from "@material-ui/core/Button";

const Demo = () => {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState({});

  const fetchData = async () => {
    setLoading(true);
    const response = await callAPI();
    if (response.status === 200) {
      setData(response.data);
    }
    setLoading(false);
  };

  return (
    <div>
      <Button disabled={loading} onClick={() => fetchData()}>
        Fetch Data
      </Button>
      <p>{JSON.stringify(data)}</p>
    </div>
  );
};

export default Demo;

Ответы [ 2 ]

0 голосов
/ 20 января 2020

Вы можете объединить ваши состояния в один составной объект состояния и сделать что-то вроде этого ...

import React, { useState } from "react";
import Button from "@material-ui/core/Button";

const Demo = () => {
  const [demoState, setDemoState] = useState({data: null, loading: false});

  const fetchData = () => {
    setDemoState({...demoState, loading: true});
    callAPI()
      .then( response => handleResponse(response)} );
  }

  const handleResponse = (response) => {
    if (response.status === 200) {
      setDemoState({data: response.data, loading: false});
    } else {
      setDemoState({...demoState, loading: false});
    }
  }

  return (
    <div>
      <Button disabled={loading} onClick={() => fetchData()}>
        Fetch Data
      </Button>
      <p>{JSON.stringify(demoState.data)}</p>
    </div>
  );
};

export default Demo;
0 голосов
/ 20 января 2020

Я думаю, вы можете избежать этой загрузки как автономной логической переменной вместо части состояния компонента. Другой подход заключается в использовании useEffect для задержки вызова API до изменения переменной loading. Этот ответ покрыл вас. И, наконец, вы можете использовать компоненты класса - функция setState() принимает обратный вызов в качестве второго параметра - это был способ изменения состояния атома c до того, как зацепки вступили в действие.

...