Reputation: 113
I want to fetch data with useEffect. With the first function, I get event details and with the second function, I get questions, which are related to the event (by ID). Fetching data for the event is successful, but second fetching data for the questions is not successful (sometimes is successful). Why fetching data once is successful, but the second time is not successful?
The output of console log:
Quiz.js:23 {active: true, _id: "6012eafe7813901034e77fb3", nameOfEvent: "Udalost 3", creatorId: "5fd23fb7b1a3a005cc82225d", participants: Array(0), …}
Quiz.js:45 {}
Quiz.js:23 {active: true, _id: "6012eafe7813901034e77fb3", nameOfEvent: "Udalost 3", creatorId: "5fd23fb7b1a3a005cc82225d", participants: Array(0), …}active: truecodeEvent: "udalost1"createdAt: "2021-01-28T16:49:02.374Z"creatorId: "5fd23fb7b1a3a005cc82225d"nameOfEvent: "Udalost 3"participants: []updatedAt: "2021-02-01T16:52:45.471Z"__v: 0_id: "6012eafe7813901034e77fb3"__proto__: Object
Quiz.js:45 {}
File Quiz.js
const Quiz = () => {
const dataForQuiz = getUserDataToQuiz();
const [eventValues, setEventValues] = useState({});
const [questionBankOfEvent, setQuestionBankOfEvent] = useState({});
const initDataToEvent = () => {
getEventByEventCode(dataForQuiz.codeEvent).then(data => {
if (!data.error) {
setEventValues(data);
}
else {
console.log(data.error);
}
})
}
console.log(eventValues);
const initQuestionsForQuiz = () => {
if (eventValues) {
getQuestionsToEvent(eventValues._id).then((data) => {
if (!data.error) {
setQuestionBankOfEvent(data);
}
else {
console.log(data.error);
}
})
}
}
useEffect(() => {
initDataToEvent();
if(eventValues){
initQuestionsForQuiz();
}
}, []);
console.log(questionBankOfEvent);
const formQuiz = () => {
return(
<>
<h1>Quiz</h1>
</>
);
}
return (
<>
{formQuiz()}
</>
);
}
export default Quiz;
Upvotes: 2
Views: 48
Reputation: 403
Probably, due to the fact that both are in the same useEffect, since react doesn´t update useState instantly. I would separate them in two different useEffect, being:
useEffect(() => {
initDataToEvent();
}, []);
useEffect(() => {
if(eventValues){
initQuestionsForQuiz();
}
}, [eventValues]);
Upvotes: 1
Reputation: 905
On the first render of your component, you execute
initDataToEvent();
if(eventValues){
initQuestionsForQuiz();
}
initDataToEvent
is supposed to update eventValues. So you expect initQuestionsForQuiz
to be executed.
But, by the time if(eventValues)
is evaluated, setEventValues
has been fired, but the eventValues
state has not been modified yet.
Hence, if you modify your code to:
useEffect(() => {
initDataToEvent();
console.log(eventValues);
if(eventValues){
initQuestionsForQuiz();
}
}, []);
You would observe eventValues
to be empty.
In React, it is best practice to split events and logic. In your case, you want initQuestionsForQuiz
to be run when eventValues
has been updated and not empty. Modifying your code to:
useEffect(() => {
initDataToEvent();
}, []);
useEffect(() => {
if(eventValues){
initQuestionsForQuiz();
}
}, [eventValues]);
should make it work. What this code does is that the function given as argument to the seconde useEffect
will be run every time eventValues
is modified.
Upvotes: 2