I have a functional component that retrieves data from an http request on page load and updates the state to store that data using useState. I then try to map out a nested array (polls.pollOptions) from the data, I get an error: "TypeError: Cannot read property 'map' of undefined". If i remove the map function and check the React component extension, I can see that the state was updated and it has the correct data. So why doesn't this render to the screen & why receive an error when the data is there to map through? Heres my component:
import React, { useState, useEffect } from "react";
import axios from "axios";
import { useParams } from "react-router";
export const EditPolls2 = () => {
const { _id } = useParams();
const [polls, setPolls] = useState([]);
useEffect(() => {
axios.get(`/polls/${_id}`).then((p) => {
setPolls(p.data);
});
}, [_id]);
return (
<div>
<p>edit polls 2</p>
<div>
<ul>
{polls.pollOptions.map((p) => (
<li key={p.pollId}>{p.option}</li>
))}
</ul>
</div>
</div>
);
};
Your current initial state is an empty array, and you are trying to access pollOptions
, which is a property that doesn't exist on an empty array.
If you don't need anything, but pollOptions
, leave the initial state as an empty array, use polls
and not polls.pollOptions
when mapping the data, and make sure to set pollOptions
as the state:
export const EditPolls2 = () => {
const { _id } = useParams();
const [polls, setPolls] = useState([]);
useEffect(() => {
axios.get(`/polls/${_id}`).then((p) => {
setPolls(p.data.pollOptions); // set the pollOptions array as the state
});
}, [_id]);
return (
<div>
<p>edit polls 2</p>
<div>
<ul>
{polls.map((p) => ( // use polls and not pollOptions
<li key={p.pollId}>{p.option}</li>
))}
</ul>
</div>
</div>
);
};
If you do need the entire object (data
) in the state, don't use initial state, and use optional chaining (?.
) when mapping the array. If the state is undefined
, the mapping would be skipped:
export const EditPolls2 = () => {
const { _id } = useParams();
const [polls, setPolls] = useState(); // no initial state
useEffect(() => {
axios.get(`/polls/${_id}`).then((p) => {
setPolls(p.data);
});
}, [_id]);
return (
<div>
<p>edit polls 2</p>
<div>
<ul>
{polls.pollOptions?.map((p) => ( // optional chaining
<li key={p.pollId}>{p.option}</li>
))}
</ul>
</div>
</div>
);
};