Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
210 views
in Technique[技术] by (71.8m points)

javascript - ReactJS : TypeError: Cannot read property 'item' of undefined

I am having trouble with a little React Router exercise

I have a File "ItemDetail.js" in which i define a Componenet "ItemDetail" which is called by a Route from another Component like so: <Route path="/shop/:id" component={ItemDetail}/>. This is my code:

import React, {useState, useEffect} from "react";

function ItemDetail({ match }) {

    const [item, setItem] = useState({});
    console.log(match);

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

    
    const fetchItem = async () => {
        const data = await fetch(`https://fortnite-api.theapinetwork.com/item/get?id=${match.params.id}`);
        const item = await data.json();
        setItem(item);
        console.log(item);
    }


    return (
      <div>
          <h3>Item: {item.data.item.name}</h3>
      </div>
  );
}

export default ItemDetail;

The id of the path is an id that i need for the API call (over match.params.id).

The fetchItem() method fetches the data I need as a JSON, I then save it in the state item and then render my render stuff. But it throws an error with : "TypeError: Cannot read property 'item' of undefined" in the line where i access item.data.name from JSX.

Weird thing is: when I change <h3>Item: {item.data.item.name} </h3> to <h3>Item: </h3> and then back to <h3>Item: {item.data.item.name} </h3> It works, just this one time, and when i refresh or navigate through my site to this path again it throws this error again


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need control it because react renders before you get item. You can edit like this : So it will check when you got item it will render the page.

import React, {useState, useEffect} from "react";

function ItemDetail({ match }) {

    const [item, setItem] = useState({});
    console.log(match);

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

    
    const fetchItem = async () => {
        const data = await fetch(`https://fortnite-api.theapinetwork.com/item/get?id=${match.params.id}`);
        const item = await data.json();
        setItem(item);
        console.log(item);
    }


    return (
      <div>
         <h3>Item: {item && item.data && item.data.item ? item.data.item.name : "Loading..."}</h3>
      </div>
  );
}

export default ItemDetail;

Also you can use optional chaining for the short solution : <h3>Item: {item?.data?.item ? item.data.item.name : "Loading..."}</h3>


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...