当我使用updateCorrectAnswers与下面的useEffect。它没有更新我的正确答案。它只显示空数组。当一组新的API调用出现时,它会显示我的旧数据。我不明白为什么。显示旧数据和空数据的Console.log图像
我重新访问了一些关于它的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,但是没有用。
这是因为您调用console.log的函数与调用设置正确答案的函数相同。当你更新状态时,它不会在同一渲染中同步发生,所以当你在updateCorrectAnswers之后记录correctAnswers时,状态仍然是[]。但是当您更改状态时,将触发呈现,其中状态现在是更新后的状态。为了能够看到它,你可以在应用程序的某个地方弹出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>
);
文档中的这篇文章可以帮助你更好地理解这一点。
当您调用' updateCorrectAnswers(); '时,correctAnswers仅在下一次呈现时更新。您的控制台日志在相同的渲染中运行,使用旧的结果。
您在更新时访问相同状态变量correctAnswers
的值的问题。更新后的值只在下次渲染时可用。
您可以使用useEffect
代替,如下所示。
useEffect(() => { if (isFetched) { console.log({ correctAnswers }); } }, [isFetched]);