kdam
kdam

Reputation: 191

How to get API results to screen?

This error occurs when I fetch data from API.

TypeError: Cannot read property 'length' of undefined

Below code represents the main page of my project. I want to display 20 of array items on the main page.

App.js

import React, { useState, useEffect } from "react" 
import banner from "./assets/marvel-group.jpg"    
import Details from "./components/details"

const CHARACTERS_API =
  "https://gateway.marvel.com:443/v1/public/characters?ts=thesoer&apikey=dkauyjs586ddh&hash=4b59bfb18ff6660c1f6alimit=20"

const theme = createMuiTheme({
  palette: {
    primary: {
      main: "#202020",
    },
  },
})

function App() {
  const classes = useStyles()

  const [characters, setCharacters] = useState([])

  useEffect(() => {
    fetch(CHARACTERS_API)
      .then((res) => res.json())
      .then((data) => {
        console.log(data)
        setCharacters(data.results)
      })
  }, [])

  return (
    <>
      <div>
        <img src={banner} alt="banner" width="100%" height="50%" />
      </div>
      <div>
        {characters.length > 0 && characters.map((character) => <Details />)}
      </div>
    </>
  )
}

export default App

Details.js

import React from "react"

const Details = () => <div>character</div>

export default Details

Here is API data.

enter image description here

Upvotes: 0

Views: 215

Answers (4)

Quentin Grisel
Quentin Grisel

Reputation: 4987

Fetching data is an asynchronous process, therefore you need to wait for the result before to display something that depends on it.

An easy solution is to add a loader while your data are loading :

if (!characters){
  return <>Loading</>;
}

return (
  //... your default view
)

else you could make your UseEffect asynchronous as follow :

import React from "react";
import { render } from "react-dom";
import "./style.css";

const App = () => {
  const [data, setData] = React.useState(null);
  React.useEffect(() => {
    fetchData();
  }, []);

  const fetchData = async () => {
    const data = await fetch("https://randomuser.me/api/");
    setData(await data.json());
  };

  if (!data) return <>Loading...</>;
  
  return (
    <div>
      <pre>{JSON.stringify(data)}</pre>
    </div>
  );
};

render(<App />, document.getElementById("root"));

Here is the stackblitz if you want to check it.

Upvotes: 0

Borjante
Borjante

Reputation: 10517

My guess is that data.response is undefined, that's why you get the error.

Try this:

useEffect(() => {
    fetch(CHARACTERS_API)
      .then((res) => res.json())
      .then((data) => {
        console.log(data)
        setCharacters(data.data.results)
      })
  }, [])

Upvotes: 1

KolisbikBoh
KolisbikBoh

Reputation: 85

use this operator https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Optional_chaining or sth

characters && (characters.length > 0 && characters.map((character) => <Details />)

Upvotes: 0

Varun Pradhan
Varun Pradhan

Reputation: 607

This might work on your case can you try this once just add characters ahead of characters.length

 <div>
            {characters && characters.length > 0 && characters.map((character) => <Details />)}
    </div>

Upvotes: 0

Related Questions