React自定义Hook使用Axios时出现Cannot read properties of undefined错误
问题分析与解决
1. 核心错误:变量解构名称不匹配
你的自定义Hook useAxios 返回的对象属性是 response、error、loading,但组件里解构时错误写成了 playerResponse、playerError、playerLoading。这会导致 playerResponse 实际是 undefined,自然无法读取 result 属性,触发 Cannot read properties of undefined (reading 'result') 报错。
2. 次发问题:渲染流程中直接调用setState
即使解构名称正确,你在组件顶层直接写 if (response !== null ) { setPlayerData(response.result); } 会引发无限重渲染:每次调用 setPlayerData 触发组件重新渲染,渲染时又会执行该条件判断,再次调用 setState,形成死循环。
3. 自定义Hook的潜在问题
- axios请求参数顺序错误:get请求的第二个参数是配置对象,而非单独的headers和body,当前写法会把headers当作data传递,不符合axios API规范。
- headers默认值处理冗余:用
JSON.stringify转成字符串再JSON.parse解析完全没必要,直接用对象即可。 - baseURL设置冲突:同时配置
axios.defaults.baseURL和自定义baseURL,可能导致请求地址混乱。
修正后的代码
自定义Hook:useAxios.js
import { useState, useEffect } from 'react'; import axios from 'axios'; // 统一设置baseURL,避免冲突 axios.defaults.baseURL = 'http://127.0.0.1:5000/v1/test_server/'; const useAxios = ({ url, method='get', data = null, headers = { accept: '*/*' } }) => { const [response, setResponse] = useState(null); const [error, setError] = useState(''); const [loading, setLoading] = useState(true); const fetchData = async () => { try { const config = { method, url, headers, // 根据请求方法处理数据:get用params,post/put用data ...(method.toLowerCase() === 'get' ? { params: data } : { data }) }; const res = await axios(config); setResponse(res.data); } catch (err) { setError(err.message || '请求失败'); } finally { setLoading(false); } }; useEffect(() => { fetchData(); }, [method, url, data, headers]); return { response, error, loading }; }; export default useAxios;
组件使用示例
import { useState, useEffect } from 'react'; import useAxios from './useAxios'; const PlayerComponent = () => { const [playerData, setPlayerData] = useState(); // 正确解构,用别名区分不同请求的返回值 const { response: playerResponse, error: playerError, loading: playerLoading } = useAxios({ url: 'player/get_player' }); // 用useEffect监听response变化,避免无限重渲染 useEffect(() => { if (playerResponse) { setPlayerData(playerResponse.result); console.log("Response", playerResponse.result); } }, [playerResponse]); if (playerLoading) return <div>加载中...</div>; if (playerError) return <div>错误:{playerError}</div>; return ( <div> {playerData && <div>玩家数据:{JSON.stringify(playerData)}</div>} </div> ); }; export default PlayerComponent;
内容的提问来源于stack exchange,提问作者PRJ
相关产品推荐
相关产品推荐

