0

I am trying to populate the list of objects with data from an array retrieved with an API call. I do get correct data (can console.log the object) but using it in code does not work. I have tried multiple solutions but nothing worked so far and I am stuck, before spending another 2 days on that I wanted to ask for your help. I am sure this is something simple I still haven't learned yet.

TypeError: Cannot read properties of undefined (reading 'map')

const EventCarousel = () => {
  const [data, setData] = useState([]);
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(true);
    axios

      .get(
        "https://cdn.contentful.com/spaces/qqdjjpwbe10z/environments/master/entries?access_token=PRIVATE_TOKEN"
      )
      .then((res) => {
        console.log(res.data.items[0].fields.imageUrl);
        setData(res.data);
      })
      .catch((error) => {
        setError(error.message);
      })
      .finally(() => {
        setLoading(false);
      });
  }, []);

if (loading) {
    return <p>Data is loading...</p>;
  } else
    return (

 {data.items.map((item) => (
            <div>
              <Event
                imageUrl={item.fields.imageUrl}
                title={item.fields.title}
                text={item.fields.text}
                linkUrl={item.fields.linkURL}
                location={item.fields.location}
                date={item.fields.date}
              />
            </div>
          ))}

The JSON structure looks as follows:

{
"sys": {},
"total": 2,
"skip": 0,
"limit": 100,
"items": [
{
"metadata": {},
"sys": {},
"fields": {
"title": "Second Event",
"text": "This is decription of a second event",
"imageUrl": "https://i.imgur.com/ULO8mVt.png",
"linkUrl": "https://www.moabit.world",
"location": "Second Location",
"date": "second date"
}
},
{
"metadata": {},
"sys": {},
"fields": {
"title": "First Event",
"text": "This is first fetched text",
"imageUrl": "https://i.imgur.com/ULO8mVt.png",
"linkUrl": "https://www.facebook.com",
"location": "First location",
"date": "First date"
}
}
]
}

THANK YOU

1
  • Why do you think your data has an items property? Commented Jul 11, 2022 at 9:53

2 Answers 2

1

It's because when your component gets mounted, It doesn't have data.items field as your initial data would be [].

You need to first set your initial state to contain {} and then update data.items to behave conditionally.

Try following solution:

const EventCarousel = () => {
  const [data, setData] = useState({});
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(true);
    axios

      .get(
        "https://cdn.contentful.com/spaces/qqdjjpwbe10z/environments/master/entries?access_token=PRIVATE_TOKEN"
      )
      .then((res) => {
        console.log(res.data.items[0].fields.imageUrl);
        setData(res.data);
      })
      .catch((error) => {
        setError(error.message);
      })
      .finally(() => {
        setLoading(false);
      });
  }, []);

if (loading) {
    return <p>Data is loading...</p>;
  } else
    return (

 {data?.items?.length ? data.items.map((item) => (
            <div>
              <Event
                imageUrl={item.fields.imageUrl}
                title={item.fields.title}
                text={item.fields.text}
                linkUrl={item.fields.linkURL}
                location={item.fields.location}
                date={item.fields.date}
              />
            </div>
          )) : null}
Sign up to request clarification or add additional context in comments.

1 Comment

In conjunction with 1st answer, it works now as it supposed to, thanks!
1

You initial your state as an array useState([]) but you using it as an object data.items, either pick one of them:

const [data, setData] = useState({items: []});
setData(res.data)

// Or
const [data, setData] = useState([]);
setData(res.data.items)

1 Comment

Thank you!! It seems to have done the job :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.