React自定义useFetch Hook返回两次数据含null引发报错如何修复
问题原因
你遇到的报错和多次打印属于正常的React渲染逻辑,核心问题有两个:
useFetch的loading初始值设置错误,默认是false,导致组件第一次渲染时,请求还未发起就直接进入表格渲染逻辑,此时data初始值为null,调用data.data.map直接触发空值报错- 多次打印是正常的多轮渲染输出:第一次是组件初始化渲染,请求未返回时
data为null;后续请求状态更新、数据返回时都会触发重渲染,输出对应状态的data值。如果项目开启了React严格模式,会多一次重复渲染,属于正常情况。
修复方案
分两步修改即可解决问题:
第一步:修正useFetch的初始加载状态
将loading初始值设为true,避免请求未开始时就进入内容渲染逻辑:
import { useState, useEffect } from "react"; import axios from "axios"; const useFetch = (url) => { const [data, setData] = useState(null); // 初始设为true,组件挂载后默认处于加载状态 const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { setLoading(true); axios .get(url) .then((response) => { setData(response.data); }) .catch((err) => { setError(err); }) .finally(() => { setLoading(false); }); }, [url]); return { data, loading, error }; }; export default useFetch;
第二步:给表格组件增加异常分支处理和空值保护
补充错误状态的 fallback UI,同时增加data非空判断做双重保险,还要给循环的元素加key属性避免React报警告:
import React from "react"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; import TableCell from "@mui/material/TableCell"; import TableContainer from "@mui/material/TableContainer"; import TableHead from "@mui/material/TableHead"; import TableRow from "@mui/material/TableRow"; import useFetch from "./custom_hooks/useFetch"; const TableComponent = () => { const { data, loading, error } = useFetch( "https://gorest.co.in/public/v1/users?page=1" ); if (loading) return <h1> LOADING...</h1>; // 错误状态返回提示UI if (error) return <h1>数据加载失败,请稍后重试</h1>; // 双重非空判断,避免异常场景下data为空 if (!data?.data) return null; console.log(data); return ( <TableContainer> <Table> <TableHead> <TableRow> <TableCell>User Names</TableCell> <TableCell align="right">Email</TableCell> <TableCell align="right">Status</TableCell> <TableCell align="right">Gender</TableCell> <TableCell align="right">ID</TableCell> </TableRow> </TableHead> <TableBody> {data.data.map((user) => { return ( <TableRow key={user.id}> <TableCell>{user.name}</TableCell> </TableRow> ); })} </TableBody> </Table> </TableContainer> ); }; export default TableComponent;
内容的提问来源于stack exchange,提问作者ahmedskulj10
相关产品推荐
相关产品推荐

