无法映射从自定义 useFetch() 挂钩获取的数据

Can't map fetched data from custom useFetch() hook

我创建了一个自定义 useFetch() 挂钩,这样我就可以使我的代码更加动态并减少重复。问题是我无法在 App.js.

中显示我的数据

我收到这些错误:

Cannot read properties of undefined (reading 'map').

react-dom.development.js:67 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

我做了一个 console.log(genres) 来查看我的自定义挂钩是否有任何错误,但它工作正常,记录了所有类型。当我尝试使用 map 方法显示我的数据时,问题就出现了。

代码沙盒link

useFetch.js

import { useReducer, useEffect } from "react";
import axios from "axios";

const ACTIONS = {
  API_REQUEST: "api-request",
  FETCH_DATA: "fetch-data",
  ERROR: "error",
};

const initialState = {
  data: [],
  loading: false,
  error: null,
};

function reducer(state, { type, payload }) {
  console.log(payload);
  switch (type) {
    case ACTIONS.API_REQUEST:
      return { ...state, data: [], loading: true };
    case ACTIONS.FETCH_DATA:
      return { ...state, data: payload, loading: false };
    case ACTIONS.ERROR:
      return { ...state, data: [], error: payload };
    default:
      return state;
  }
}

function useFetch(url) {
  const [state, dispatch] = useReducer(reducer, initialState);
  useEffect(() => {
    dispatch({ type: ACTIONS.API_REQUEST });
    axios
      .get(url)
      .then((res) => {
        dispatch({ type: ACTIONS.FETCH_DATA, payload: res.data });
      })
      .catch((e) => {
        dispatch({ type: ACTIONS.ERROR, payload: e.error });
      });
  }, [url]);
  return state;
}

export default useFetch;

App.js

import "./styles.css";
import useFetch from "./useFetch";

export default function App() {
  const BASE_URL =
    "https://api.themoviedb.org/3/genre/movie/list?api_key=${API_KEY}";
  const { data: genres, loading, error } = useFetch(BASE_URL);
  console.log(genres);
  return (
    <div className="App">
      {genres.genres.map((genre) => (
        <div key={genre.id}>{genre.name}</div>
      ))}
    </div>
  );
}

您的初始状态有 data 个数组:

const initialState = {
  data: [],
  loading: false,
  error: null,
};

并且您的 App 组件在加载后立即尝试读取该数组上的 属性 genres。具有该名称的数组上没有 属性,因此 genres.genres 未定义,对其进行映射调用将引发错误。

我会将 initialState.data 初始化为 {genres: []},方法是将数据容器作为另一个参数传递给您的挂钩,而不是将其硬编码到挂钩文件中。

function useFetch(url, data) {
  const [state, dispatch] = useReducer(reducer, {...initialState, data});
  ...
}
const { data: genres, loading, error } = useFetch(BASE_URL, {genres: []});