简体   繁体   中英

React Hooks Not Allowing Me to Display Single Objects After Fetch Call

I am calling a standard JSON file using fetch on a React Hooks project. (I'm mocking a server using JSON-Server to read the local json file)

In my main function, I'm calling a variable and a function, like any normal React Hook, and setting it to an empty array because I'm calling API data using fetch.

let [items, setItems] = useState([]);

Then I'm making my actual fetch call to my mock server

    const fetchItems = async () => {
        const url = "http://localhost:3002/learn";
        const response = await fetch(url);
        items = await response.json();
        setItems(items);
        console.log(items[0].title);
    }

The console.log(items[0].title) does in fact return the correct value.

If I wanted to display all results, the following would even work.

{items.map((item) => 
   <img src={item.source} alt={item.title} title={item.title}  className="img-fluid mx-auto d-block" />
)}

However, once I want to display a single value in my return, I get an error message saying: "TypeError: Cannot read property 'source' of undefined" The code that I'm using, just to test at first is the same exact thing as my console.log from before.

<img src={items[0].source} alt={items[0].title} title={items[0].title}  className="img-fluid mx-auto d-block" />

Am I missing a major step that allows me to use the fetched info in my return?

If I were to hard-code my JSON data on the same component, it would work. I feel like it has something to do with fetch. I was looking at this question, and it's similar, but not the same thing. I'm also using hooks and also not axios. Can't display data after fetch

UPDATE: The JSON file looks something like this:

{
    "learn": [
      {
        "id": 1,
        "title": "Angular JS",
        "source": "./images/logo-angular-js.png"
      },
      {
        "id": 2,
        "title": "Firebase",
        "source": "./images/logo-firebase.png"
      },
      {
        "id": 3,
        "title": "GraphQL",
        "source": "./images/logo-graphql.png"
      }
    ]
}

On your first render, items has a length of 0, so items[0] is going to be undefined . You're likely trying to render before that first item has loaded.

Check if items[0] is defined before trying to access items[0].source and the like.

function YourComponent() {
  const [items, setItems] = useState([]);

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

  const fetchItems = async () => {
    const url = "http://localhost:3002/learn";
    const response = await fetch(url);
    items = await response.json();
    setItems(items);
    console.log(items[0].title);
  }

  if (!items.length) {
    return null;
  }

  return (
    <img 
      src={items[0].source}
      alt={items[0].title}
      title={items[0].title}
      className="img-fluid mx-auto d-block" /> 
  );
}

On the first render, this will cause nothing to be output. After the setItems call is made, the component will re-render, and this time (if there were items being set), it'll render your item.

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