- Your 2nd
setAnswer may point to the old answers array as calling setAnswer can async.
const [index, setIndex] = useState(0);
const [answers, setAnswers] = useState([]);
useEffect(()=>{
(async () => {
const data = await fetch ('');
const json = await data.json();
setAnswers(json.results[index].incorrect_answers);
// answers may equal to []
answers.splice(random,0, json.results[index].correct_answer);
setAnswers(answers)
})();
}, []);
- React will batch your two
setAnswers calls and will only call the 2nd setAnswer. So your incorrect_answers will never set to the answers array. Therefore you are actually splicing the initial empty array.
- You are mutating the original data. so somehow if you manage to set the
incorrect_answers before insert the correct_answer and still uses answers.splice, then the original data will be mutate. So after you mutate the original data set, you call the setAnswers(answers) with mutated data. When react compares the old value to the new value provided in setAnswers it sees both are equal. So React will ignore state update.
How you can fix the issue
const [index, setIndex] = useState(0);
const [answers, setAnswers] = useState([]);
useEffect(()=>{
(async () => {
const data = await fetch ('');
const json = await data.json();
const data = json.results[index].incorrect_answers;
data.splice(random,0, json.results[index].correct_answer);
setAnswers(data);
})();
}, []);
References
- https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
- https://reactjs.org/docs/react-component.html#state
UPDATE
I have update your QuizeComponent
function QuizComponent() {
const [APIData, setAPI] = useState({});
const [question, setQuestion] = useState("");
const [index, setIndex] = useState(0);
const [answers, setAnswers] = useState([]);
const [objectsLength, setObjectsLength] = useState(0);
useEffect(() => {
(async () => {
const data = await fetch(
"https://opentdb.com/api.php?amount=10&type=multiple"
);
const json = await data.json();
setAPI(json.results);
setObjectsLength(json.results.length);
})();
}, [])
useEffect(() => {
if (APIData[index]) {
const random = Math.floor(Math.random() * 5);
const data = APIData[index];
const cpy = [...data.incorrect_answers];
cpy.splice(random, 0, APIData[index].correct_answer);
setAnswers(cpy);
setQuestion(data.question);
}
}, [index, APIData])
const nextQuestion = function () {
if (index !== objectsLength.length - 1) {
setIndex(index + 1);
setQuestion(APIData[index].question);
setAnswers(APIData[index].incorrect_answers);
} else {
console.log("This is the last question.");
}
};
return (
<div className="QuizComponent">
<h1>QUIZ COMPONENT</h1>
<div>
<Question question={question} APIData={APIData} index={index} />
</div>
<div>
<button onClick={() => nextQuestion(index)}>Next question</button>
</div>
<div id="main-answers-container">
{answers.map(function (item, i) {
return <Answer key={i} answer={item} index={index} />;
})}
</div>
</div>
);
}