I am working on a Quiz App using React Context API. I used a useEffect hook for fetching quiz question data from an online API while using the start button state as a dependency. However, when I am console logging the extracted object data in Quiz.js, it seems the **API is getting called twice despite the fact that I click the "Start Quiz" button only once **(turning startQuiz state from false to true). Why is it happening? Also in the console, the logs from the child component (Quiz.js) are appearing first.
Code for App.js (Parent Component) ---->
import Quiz from "./Components/Quiz";
import { DataContext } from "./Context/DataContext";
export default function App() {
const [startQuiz, setStartQuiz] = useState(false)
const [quesList,setQuesList] = useState(null)
useEffect(()=> {
let url = "https://opentdb.com/api.php?amount=5&difficulty=easy&type=multiple"
fetch(url)
.then(data => data.json())
.then(data => {
setQuesList(data);
}).catch(err => console.log(err))
console.log(quesList)
},[startQuiz])
return (
<div className="App">
<div className="start-container">
<h1 className="heading">General Knowledge Quiz</h1>
<h5 className="sub-heading">Test your overall GK daily with these five questions</h5>
<button
className="startBttn"
onClick={()=> setStartQuiz(!startQuiz)}
>Start Quiz</button>
<DataContext.Provider value={{quesList,setQuesList}}>
{startQuiz && <Quiz/>}
</DataContext.Provider>
</div>
</div>
);
};
Code for Quiz.js (Child Component) ---->
import React ,{useContext} from 'react'
import { DataContext } from '../Context/DataContext'
export default function Quiz() {
const {quesList} = useContext(DataContext)
console.log(quesList)
const question = quesList.results[0].question;
console.log(question)
const correct_answer = quesList.results[0].correct_answer;
console.log(correct_answer)
const incorrect_answers = quesList.results[0].incorrect_answers;
console.log(incorrect_answers)
return (
<div>
<h1>Quiz</h1>
</div>
)
}
</code>```
**What is the flow of the rendering here? Note: There is no "StrictMode" present in the code ( just found out that it can cause UseEffect to render twice) **
CodePudding user response:
Whenever a state is being changed, your component is being re-rendered. Hence the reason your useEffect
is called twice.
I would suggest the following solution:
Wrap your logic with an if statement
useEffect(() => {
if (startQuiz) {
let url =
"https://opentdb.com/api.php?amount=5&difficulty=easy&type=multiple";
fetch(url)
.then((data) => data.json())
.then((data) => {
setQuesList(data);
})
.catch((err) => console.log(err));
console.log(quesList);
}
}, [startQuiz]);