reactjs React状态未更新,新数据到来时会使用旧数据进行更新

9jyewag0  于 2022-12-03  发布在  React
关注(0)|答案(3)|浏览(164)

当我使用updateCorrectAnswers和下面useEffect时,它没有更新我的正确答案。它只显示空数组。当一组新的api调用到来时,它显示我的旧数据。我不明白为什么。console.log image that shows old data and empty data
我重新浏览了一些stackoverflow关于它的帖子,但它主要是关于useEffect的,但我正在尝试useEffect的内部。如果有人需要https://github.com/hyklops/react-starter/tree/master/quiz-app,这是完整的代码

function App() {
  const [trivias, setTrivias] = useState(null);
  const [isFetched, setIsFetched] = useState(false);
  const [correctAnswers, setCorrectAnswers] = useState([]);

  const updateCorrectAnswers = () => {
    trivias.map((trivia) => {
      setCorrectAnswers((prev) => [...prev, trivia.correct_answer]);
    });
  };

  async function dataFetch() {
    const res = await fetch(
      "https://opentdb.com/api.php?amount=5&type=multiple"
    );
    const data = await res.json();
    return setTrivias(data.results);
  }

  const shuffle = (trivia, index) => {
    const answers = [...trivia.incorrect_answers, trivia.correct_answer];
    const shuffledAnswers = getRandomAnswers(answers);

    // const shuffleArray = (answer) => [...array].sort(() => Math.random() - 0.5);
    return shuffledAnswers;
  };

  const getRandomAnswers = (answers) => {
    const newAnswers = [];

    while (newAnswers.length !== 4) {
      const getRandomIndex = Math.floor(Math.random() * 4);

      const condition = newAnswers.some(
        (item) => item === answers[getRandomIndex]
      );

      if (!condition) {
        newAnswers.push(answers[getRandomIndex]);
      }
    }

    return newAnswers;
  };

  const getTrivias = () => {
    return trivias.map((trivia, index) => {
      return <Trivia question={trivia.question} answers={shuffle(trivia)} />;
    });
  };

  useEffect(() => {
    dataFetch();
  }, []);

  useEffect(() => {
    if (!!trivias) {
      setIsFetched(true);
      updateCorrectAnswers();
      console.log({ correctAnswers });
    }
  }, [trivias]);

  if (!isFetched) {
    return <h1>loading</h1>;
  }

  return (
    <div className="App">
      <div>{getTrivias()}</div>
      <div className="check">
        <button>Check Answers</button>
      </div>
    </div>
  );
}

export default App;

我试过useEffect,但没有用。

rggaifut

rggaifut1#

这是因为调用console.log的函数与设置正确答案的函数是同一个函数。当更新状态时,它不会在同一个呈现中同步发生,因此当您在 *updateCorrectAnswers * 之后记录 *correctAnswers a时,状态仍然是[]。但当您更改状态时,会触发重新呈现。其中的状态现在是更新后的状态。为了能够看到它,你可以在你的应用程序中的某个地方弹出一个console.log,如下所示:

function App() {
  const [trivias, setTrivias] = useState(null);
  const [isFetched, setIsFetched] = useState(false);
  const [correctAnswers, setCorrectAnswers] = useState([]);

  console.log({ correctAnswers });
  
  const updateCorrectAnswers = () => {
    trivias.map((trivia) => {
      setCorrectAnswers((prev) => [...prev, trivia.correct_answer]);
    });
  };

或者只是在屏幕上渲染它:

return (
    <div className="App">
      <div>{getTrivias()}</div>
      <div>{correctAnswers}</div>
      <div className="check">
        <button>Check Answers</button>
      </div>
    </div>
  );

文档中的This article可以帮助更好地理解这一点。

eqoofvh9

eqoofvh92#

当你调用'updateCorrectAnswers();',correctAnswers只会在下一次呈现时更新。您的控制台日志将在同一呈现中运行,并显示旧的结果。

wa7juj8i

wa7juj8i3#

问题是,在更新时,您正在访问同一状态变量correctAnswers的值。更新后的值仅在下次呈现时可用。
您可以使用useEffect来代替,如下所示。

useEffect(() => {
    if (isFetched) {
      console.log({ correctAnswers });
    }
  }, [isFetched]);

相关问题