Home > front end >  useEffect Hook , API getting called twice
useEffect Hook , API getting called twice

Time:01-11

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]);
  • Related