In React, how can I keep the states inside a useCallback up-to-dates?

408 Views Asked by At

I have a state named questions In a React component.

const [questions, setQuestions] = useState([]);

and a useEffect method that runs only when the component is rendered the first time.

useEffect(() => {
  let questionsArray = [];
  //some work is done here to populate the questionsArray
  setQuestions(questionsArray);
},[]);

I have a useCallback method that is created when the component is rendered for the first time.

const updateQuestion = useCallback(() =>{
  let new_questions = [...questions];
  //do some work here
},[]);

The problem is that questions state inside the updateQuestion callback is empty because when the component is rendered the first time, the questions state is empty, and the updateQuestion callback uses the stale questions state for some reason. However, the useEffect populates the questions state array, and the questions state inside updateQuestion callback is not up-to-date. I solved this problem by adding questions.length to the dependencies array of useCallback like the following

const updateQuestion = useCallback((index) =>{
  let new_questions = [...questions];
  //do some work here
},[questions.length]);

So, when the questions state is populated with new data in the useEffect, the updateQuestion callback is re-created, and the useCallback will have up-to-date data in questions state. But, are there any other ways that I can get the up-to-date questions state inside the useCallback without re-creating the callback?

Each item in questions array is used to render a child components named QuestionCard

questions.map((question, index)=>{
        return  (
            <li className="list-group-item border-0" key={question.id}>
               <QuestionCard props={question} index={index} updateQuestion={updateQuestion} />
             </li>
             );
        })

The problem is that QuestionCard is a memoized component. If I append an item to the questions state array, the existing items in questions state are the same, they don't need to be rerendered. Now, If i pass questions.array into the dependencies array, the callback is re-created, every child components is rerendered. But, I can't just skip using useCallback and just create a native function. Because, updateQuestion callback is used to update individual question item insides the questions array. If I update a single question, every question will be rerender. If I use useCallback, only the question i am updating is rerendered while i am updating it .

0

There are 0 best solutions below