когда я использую updateCorrectAnswers с useEffect ниже. это не обновляет мои правильные ответы. он показывает только пустой массив. когда приходит новый набор вызовов API, он показывает мои старые данные. Я не понимаю, почему. изображение console.info, которое показывает старые данные и пустые данные
Я пересмотрел некоторые сообщения об этом 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.info({ 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;
Я пробовал использоватьEffect, и это не сработало.





Это связано с тем, что вы вызываете console.info в той же функции, что и функцию для установки правильных ответов. Когда вы обновляете состояние, это не происходит синхронно в одном и том же рендере, поэтому, когда вы регистрируете correctAnswers сразу после updateCorrectAnswers, состояние по-прежнему []. Но когда вы меняете состояние, запускается повторный рендеринг, в котором состояние теперь является обновленным состоянием. Чтобы увидеть это, вы можете просто вставить console.info где-нибудь в своем приложении, например:
function App() {
const [trivias, setTrivias] = useState(null);
const [isFetched, setIsFetched] = useState(false);
const [correctAnswers, setCorrectAnswers] = useState([]);
console.info({ 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 на уровне, когда вы обновляете. Обновленное значение будет доступно только в следующем рендере.
Вместо этого вы можете использовать useEffect, как показано ниже.
useEffect(() => { if (isFetched) { console.info({ correctAnswers }); } }, [isFetched]);
Если вы думаете, что он не обновляется только потому, что журнал показывает пустой массив,
setStateявляется асинхронным, и операторconsole.infoвызывается до того, какsetCorrectAnswersзавершится.