简体   繁体   中英

TypeError: Cannot read property 'map' of undefined while fetching from API

I have been trying to make a simple API fetch but I can't understand what I'm doing wrong I have read many questions but I really feel like I'm missing something since everything seems correct (it obviously isn't)

import { useState } from "react";
import ProductCard from "./ArticleCard/ProductCard.js";

export default function ProductsIndex() {
  const [searchText, set_searchText] = useState("");
  const [state, set_state] = useState({ status: "idle" });
  const search = async () => {
    if (searchText === "") {
      set_state({ status: "idle" });
      return;
    }
    set_state({ status: "searching" });
    const queryParam = encodeURIComponent(searchText);
    const data = await fetch(
      /* base browser fetch  https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch*/
      `https://omdbapi.com/?apikey=6a06f383&s=${queryParam}`
    ).then((r) => r.json());
    set_state({ status: "done!", data: data.Search });
  };
  console.log(state.data);
  return (
    <div className="ProductsIndex">
      We sell movies for a high price.
      <h1>Discover some movies!</h1>
      <p>
        <input
          value={searchText}
          onChange={(e) => set_searchText(e.target.value)}
        />
        <button onClick={search}>Search</button>
      </p>{" "}
      <p>
        {state.data.map((movie) => (
          <ProductCard
            poster={movie.poster}
            title={movie.title}
            year={movie.year}
            type={movie.type}
          />
        ))}
      </p>
    </div>
  );
} 

The console.log(state.data) gives the desired result, so it's as if the data isn't being passed down.. and I don't understand why

result from console.log(state.data):

[
    {
        "Title": "Finding Nemo",
        "Year": "2003",
        "imdbID": "tt0266543",
        "Type": "movie",
        "Poster": "https://m.media-amazon.com/images/M/MV5BZTAzNWZlNmUtZDEzYi00ZjA5LWIwYjEtZGM1NWE1MjE4YWRhXkEyXkFqcGdeQXVyNjU0OTQ0OTY@._V1_SX300.jpg"
    },
    {
        "Title": "Finding Nemo",
        "Year": "2003",
        "imdbID": "tt0401422",
        "Type": "game",
        "Poster": "https://m.media-amazon.com/images/M/MV5BNGEzMjdiZGEtYzU3ZC00OGFmLWI3NTgtZTcyNTFjYTliNDg5XkEyXkFqcGdeQXVyNjExODE1MDc@._V1_SX300.jpg"
    },
    {
        "Title": "Finding Nemo Submarine Voyage",
        "Year": "2007",
        "imdbID": "tt1319713",
        "Type": "movie",
        "Poster": "https://m.media-amazon.com/images/M/MV5BMzAxMzMyODQtNWY0Yy00N2M3LWE5MDQtZDUzNjc1ZGFmMzA4XkEyXkFqcGdeQXVyMzkxMzc4Mw@@._V1_SX300.jpg"
    },
    {
        "Title": "Finding Nemo: Studio Tour of Pixar",
        "Year": "2003",
        "imdbID": "tt1248974",
        "Type": "movie",
        "Poster": "N/A"
    },
    {
        "Title": "Finding Nemo: A Filmmakers' Roundtable",
        "Year": "2012",
        "imdbID": "tt10255922",
        "Type": "movie",
        "Poster": "https://m.media-amazon.com/images/M/MV5BNjAyMTBmODQtZGYxMC00NjdhLThhN2MtODlhMDI4NTczYTMyXkEyXkFqcGdeQXVyNDEyNjEzOTg@._V1_SX300.jpg"
    }
]

Thank you for your help

You should initialize the state.data Try like this.

 const [state, set_state] = useState({ status: "idle",data:[] });

I have just fixed up couple of things:

  1. Define the sate for data

const [state, set_state] = useState({ status: "idle",data:[] });

  1. Check your array before iterating

    {state.data && state.data.map((movie) => ( <ProductCard poster={movie.poster} title={movie.title} year={movie.year} type={movie.type} /> ))}

I have created a small demo: search nemo, press button and please check the console, https://codesandbox.io/s/flamboyant-dubinsky-3bxsf?file=/src/App.js:155-219

i think i got what the problem is,., When you set a new state: it replaces the previous one. With that in mind, when you set your loading status like this:


set_state({ status: "idle" });

it actually makes your state.data undefined, so, it throws the exception.

Instead of reassigning your entire state, try replacing only the things that need to be changed:

set_state({ ...state, status: "idle" });

So, whenever tou call your set_state method, you should add your ...state , so you won't have this problem.

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