0

I've just started learning how to use React, and I encountered the following problem: I need to render this data I fetched using graphql, when I console.log the data it shows up just fine. But when I try to map the array to get what I need it seems to be returning undefined.

How can I render the name and email of each subscriber using map?

import React, { useState } from "react";
import { gql, useQuery } from "@apollo/client";

const GET_SUBSCRIBERS_QUERY = gql`
  query {
    subscribers(stage: DRAFT) {
      name
      email
      id
    }
  }
`;

const App = () => {
  const { data } = useQuery(GET_SUBSCRIBERS_QUERY);

  return (
    <>
      <h1>@fsouza/table-data</h1>
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Email</th>
          </tr>
        </thead>
        <tbody>
          {data.subscribers.map((subscriber) => (
            <tr key={subscriber.id}>
              <td>{subscriber.name}</td>
              <td>{subscriber.email}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </>
  );
};

export default App;

console.log with the data

console.log after trying to map array

2
  • add data?.subscribers.map(, data is undefined on the first render Commented Aug 7, 2022 at 20:56
  • yep, I was missing that. Thanks Commented Aug 7, 2022 at 21:43

3 Answers 3

2

Your data is optional. And it is undefined while the query is loading.

 const { data, loading } = useQuery(GET_SUBSCRIBERS_QUERY);

You may consider adding a loading state, as follow:

if (loading) {
  return <p>Loading...</p> // Or whatever you want
}

Or just ad a check for subscribers to be present already (using a question mark):

data?.subscribers.map((subscriber) => ()
Sign up to request clarification or add additional context in comments.

Comments

0

data is probably undefined before the actual fetch happens:

Change data. to data?.

const App = () => {
  const { data } = useQuery(GET_SUBSCRIBERS_QUERY);

  return (
    <>
      <h1>@fsouza/table-data</h1>
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Email</th>
          </tr>
        </thead>
        <tbody>
          {data?.subscribers.map((subscriber) => (
            <tr key={subscriber.id}>
              <td>{subscriber.name}</td>
              <td>{subscriber.email}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </>
  );
};

Comments

0

I think it is a simple question of when the data is available. So before the data has been fetched, the data property is undefined. Thus the data object doesn't have a subscribers property, which is why it's failing. When it fails you get an error, and it crashes.

If you wrap the map in a condition, you should work.

Putting data and a && in front does the trick. If data is defined (not a falsy value like undefined), execute the right-hand side.

{data && data.subscribers.map((subscriber) => (
    <tr key={subscriber.id}>
       <td>{subscriber.name}</td>
       <td>{subscriber.email}</td>
    </tr>
))}

1 Comment

thanks for the explanation! It was just as you said

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.