Show array first element that may not have been loaded using React

Asked

Viewed 43 times

-2

I am developing a quiz application using React for study purposes.

I have the state called Quiz, the same consists of:

interface QuestionData {
  id: number;
  question: string;
  explanation: string;
  options: OptionsData;
}

I would like to display only the first element of the array on the screen, I know the way to do this would be:

<p>{quiz[0].question}</p>

But this way I’m getting the following error:

TypeError: Cannot read property 'question' of undefined

If I print using console.log(quiz[0].question), I receive the desired return.

Is there any other way? Or the way I thought it was right is not?

Complete code below:

interface VideoInfo {
  video_id: number;
}

type OptionsData = any[];

interface QuestionData {
  id: number;
  question: string;
  explanation: string;
  options: OptionsData;
}

const Quiz: React.FC<VideoInfo> = video_id => {
  const [quiz, setQuiz] = useState<QuestionData[]>([]);

  const video = video_id;

  const getQuiz = useCallback(async () => {
    try {
      await api.get(`/quiz/video/${video}`).then(response => {
        setQuiz(response.data);
      });
    } catch (err) {
      alert('error');
    }
  }, [video]);

  useEffect(() => {
    getQuiz();
  }, [getQuiz]);

  return (
    <Container>
      <ol>
        <li>
          <div className="question">
            {/* O erro acontece aqui: */}
            <p>{quiz[0].question}</p>
            <div>
              <Button type="button">A</Button>
              <Button type="button">B</Button>
              <Button type="button">C</Button>
              <Button type="button">D</Button>
            </div>
          </div>
        </li>
      </ol>
    </Container>
  );
};

export default Quiz;

This is the way out of console.log(response.data) when invoked within the function getQuiz:

Array(2)
0:
  explanation: "Sempre é necessário redobrar a atenção ao sair da via para um 
  acostamente."
  id: 6
  options: (4) [{…}, {…}, {…}, {…}]
  question: "Quais cuidados ao sair da via para um acostamento?"
1:
  explanation: "Precisamos manter uma distância segura a todo momento."
  id: 7
  options: (4) [{…}, {…}, {…}, {…}]
  question: "Para que tenhamos a menor distância de frenagem:"
  • 1

    What is response.data?

  • Response is the return of the Promise that fetches the data of an API, data is an element that is within Response, which brings data array of the questions.

  • 1

    quiz[0] is undefined at the beginning. Its initial value is [] . Try the {quiz[0]?. question}

  • Sorry @Luizfelipe. I edited the question.

  • 1

    Really @Ajeetshah, the problem was this, thank you very much!

1 answer

3


You are trying to render the elements even if they have not been loaded yet. As indicated in the comments, before of api.get Having been solved, the component is already being rendered as an empty array. It will be rendered again when the array has been properly loaded.

Thus, you must ensure that something is shown while the array is still empty. One option is to check the length of the array using the property length. Something like that:

if (quiz.length === 0) {
  return <p>Carregando...</p>;
}

return <p>Primeiro item: {quiz[0].question}</p>;

So you’re making sure you only access the property question if the array has non-zero length (in this case it will always be greater than zero). This avoids the error Cannot read Property ... of Undefined.

Another option is to create another state to maintain the information of the shipment, which is more robust in most cases. If you choose to do so, you will have to keep it manually. Many people choose to call isLoading or something like.

  • 1

    Another well-used technique: (quiz[0] || {}). Question , or with the optional chaining : quiz[0]?. Question https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

  • Yes, @rgralb! : ) This was mentioned in the comments of the question and also in the other question I raised: https://answall.com/a/494172/69296 :-)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.