无法映射从自定义 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: []});
我创建了一个自定义 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: []});