0

I have a problem with useState hook. I'm trying to do some kind of tests. But I don't understand how it works. I have two components - SurveyScreen and QuestionItem:

const SurveyScreen: React.FC = () => {
    const [answersList, setAnswersList] = useState<Answer[]>([]);
    // ...

    return (
       {/* ... */}
       <QuestionItem
           completeSurvey={completeSurvey}
           answersList={answersList}
           setAnswersList={setAnswersList}
           step={step}
           setStep={setStep}
           index={index}
           question={question}
           questionsCount={survey.questions.length}
           key={question.id.toString()}
       />
    );
}
const QuestionItem: React.FC<IQuestionItemProps> = ({
  step,
  setStep,
  index,
  question,
  questionsCount,
  answersList,
  setAnswersList,
  completeSurvey,
}) => {
  const [singleAnswerId, setSingleAnswerId] = useState<number | null>(null);
  const [answersIds, setAnswersIds] = useState<number[]>([]);

  const addAnswer = (): void => {
    let answer: Answer;

    if (question.multiple && answersIds.length) {
      answer = {
        id: question.id,
        user_comment: '',
        checked: answersIds,
      };
      console.log(answer);
    } else if (singleAnswerId) {
      answer = {
        id: question.id,
        user_comment: '',
        checked: singleAnswerId,
      };
      console.log(answer);
    }

    setAnswersList(answersList => [...answersList, answer]);
    console.log(answersList); // <- [] from the first time
  };

  return (
     <TouchableOpacity
        onPress={addAnswer}
        style={{...mainStyles.alignCenterRow, marginTop: 90}}>
         <Text style={styles.continueText}>Continue</Text>
         <EvilIcons name="arrow-right" size={30} color="#007fff" />
     </TouchableOpacity>
  );
}

When I try to add the answer to list, it doesn't update the array from the first time. It outputs empty array.

What am I doing wrong and how can I fix it?

UPD: I don't need useEffect hook and I've already tried something like this:

setMovies(prevMovies => ([...prevMovies, ...result]));
setAnswersList(answersList => [...answersList, answer]); // my code

It doesn't help me.

Shadowman
  • 245
  • 3
  • 11
  • That's because setState from the useState hook doesn't accept callbacks, it only works for class components. Change `setAnswersList(answersList => [...answersList, answer]);` to `setAnswersList([...answersList, answer]);` – slaid3r Mar 23 '21 at 03:03
  • @slaid3r Ummm...first article in Google https://daveceddia.com/usestate-hook-examples/, 'Updating state based on previous state'. However, I tried your method and it also didn't help me. – Shadowman Mar 23 '21 at 07:26
  • My bad, confused callback for setting state based on previous value with callback called after state was update which is only available to class components. – slaid3r Mar 23 '21 at 07:46
  • Oh, I see now, setState is not synchronous so the commented console log will show previous value. Your state should be fine, just move the console.log outside the addAnswer and you'll see that it is changed after calling the addAnswer function. – slaid3r Mar 23 '21 at 07:49

0 Answers0