React自定义Hook useFetch报错且无法获取数据求助
React自定义Hook useFetch报错且无法获取数据求助
嘿,我仔细看了你的代码,发现几个关键问题导致你拿不到数据,咱们一步步来修复:
1. 最致命的错误:解构方式不对
你的useFetch Hook返回的是单个data值,但你在App组件里用了数组解构const [data] = useFetch(...),这会导致data变成undefined——因为单个值无法被数组解构出第一个元素,正确的做法是直接赋值或者改成返回对象后用对象解构。
2. 缺少请求状态管理与错误处理
你的Hook里没有处理请求加载中、请求失败的情况,也没处理HTTP错误(比如404、500这类状态码,fetch不会自动把它们当成reject),这会让你不知道请求到底是在加载还是真的失败了。
3. 未处理组件卸载后的请求泄漏
如果组件在请求完成前卸载,fetch请求还会继续,可能导致内存泄漏和控制台警告。
修改后的完整代码
useFetch Hook:
import { useEffect, useState } from "react"; const useFetch = (url) => { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { // 创建AbortController用于取消请求 const controller = new AbortController(); fetch(url, { signal: controller.signal }) .then((res) => { // 检查HTTP响应是否正常 if (!res.ok) { throw Error("请求数据失败,请检查网络或URL是否有效"); } return res.json(); }) .then((responseData) => { setData(responseData); setLoading(false); setError(null); }) .catch((err) => { // 忽略取消请求的错误 if (err.name !== "AbortError") { setError(err.message); setLoading(false); } }); // 组件卸载时取消请求 return () => controller.abort(); }, [url]); // 返回包含状态的对象,方便组件解构使用 return { data, loading, error }; }; export default useFetch;
App组件:
import React from 'react'; import useFetch from './useFetch'; const App = () => { // 用对象解构获取返回的状态 const { data, loading, error } = useFetch("https://jsonplaceholder.typicode.com/todos"); console.log(data); // 处理加载中状态 if (loading) return <div>数据加载中...</div>; // 处理错误状态 if (error) return <div>出错了:{error}</div>; return ( <div> {data && data.map((item)=>(<p key={item.id}>{item.title}</p>))} </div> ) } export default App;
关键修改点说明:
- 把
useFetch的返回值改成包含data、loading、error的对象,用对象解构更灵活,也避免了之前的解构错误 - 添加
loading状态,让你能看到请求还在进行中,不会误以为拿不到数据 - 处理HTTP错误:通过
res.ok判断响应状态,抛出错误后进入catch块 - 用
AbortController取消组件卸载后的请求,避免内存泄漏 - 错误处理时排除
AbortError,因为取消请求属于正常操作,不需要展示给用户
这样修改后,你应该就能正常获取并渲染数据了,如果还是有问题,可以打开浏览器控制台看看有没有具体的错误提示,再针对性排查~
内容来源于stack exchange
相关产品推荐
相关产品推荐

