简体   繁体   中英

TypeError: Cannot read property 'map' of undefined (React)

I have this code userPage that is suppose to fetch data from an online JSONplaceholder of users and output it based on ID. Currently my i am fetching the data correctly, but when I try to render it, I get the error "TypeError: Cannot read property 'map' of undefined" for some reason. Not sure why, I feel like it is a small error but I have been racking my brain for hours trying to figure it out.

UserPage

export const UserPage = ({match}) => {
const [data, setData] = useState({ hits: [] });

useEffect(() => {
    function getFetchUrl() {
        return `https://jsonplaceholder.typicode.com/users/${match.params.id}`;
    }

    async function fetchData() {
        const result = await axios(getFetchUrl());
        setData(result.data);
    }

    fetchData();
}, [match.params.id]);

console.log(data)
return (
    <>
        <ul>
            {data.hits.map(item => (
                <li key={item.id}>
                    <a href={item.url}>{item.title}</a>
                </li>
            ))}
        </ul>
    </>
);

}

all of the api data is stored inside hits, but this is how the data in hits looks like when I console.log(data) after making the API call in useEffect

在此处输入图像描述

as you can see, the data is correct, but the first time it runs, hits: Array{0}. The data is the correct output after that call. I feel like this might be the problem, but I'm not quite sure and I don't know how to fix it. Also, I'm not sure why it made the call 3 times, but I don't know if that matters either. I am new to React.JS so I'm figuring out all these things as I go along.

Thank you!

If you want the state to be an object, then you need to update it like one. As per your current code, you are replacing the object in state data with what you get from api which causes your model to break

 async function fetchData() {
    const result = await axios(getFetchUrl());
    setData({hits: result.data}); // pass an object
}

Also note that state updates with hooks do not merge the state, so say you have multiple keys in the object and you would like to update only one, you need to merge and update it like

setData(prev => ({
   ...prev,
   hits: result.data
}))

Add a boolean variable, initialise it as false then set it to true once axios promise is recieved. And console your data when this boolean is true.

export const UserPage = ({match}) => {
const [data, setData] = useState({ hits: [] });
const [fetched, setFetched] = useState(false);
useEffect(() => {
    function getFetchUrl() {
        return `https://jsonplaceholder.typicode.com/users/${match.params.id}`;
    }

    async function fetchData() {
        const result = await axios(getFetchUrl());
        setData(result.data);
        setFetched(result.data && true);
    }

    fetchData();
}, [match.params.id]);

fetched && console.log(data)

i hope this will solve the error with console log.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM