React中如何让axios get请求仅执行一次且可正常向子组件传值
问题根因分析
- 闭包与依赖缺失问题:你的useEffect传入空依赖数组,内部调用的getUploads函数引用了
authToken、uploadsData、push等外部变量,这些变量更新时useEffect不会重新执行,函数内拿到的永远是组件首次渲染时的初始值,同时React会抛出依赖缺失的警告,也就是你看到的蓝色!提示。 - State更新逻辑错误:你在请求成功后直接用
[...uploadsData, resp]拼接数据,这里的uploadsData因为闭包永远是初始空数组,而且你把整个响应对象resp塞进去了,实际接口返回的有效数据应该是resp.data。 - Route组件写法错误:你用
component={() => <Gallery data={uploadsData}/>}的写法传递props,每次App组件重渲染时都会生成新的匿名函数,导致Gallery组件被反复卸载挂载,所以控制台会多次打印数据。 - Gallery组件参数接收错误:组件的入参是整个props对象,你直接写
(data)接收的是props本身,而非props里的data属性,这也是你无法正常访问数据的原因之一。
修复方案
1. 修复App.js逻辑
修改后的完整代码如下:
import { useEffect, useState, useCallback } from 'react'; import { BrowserRouter as Router, Switch, Route, useHistory} from 'react-router-dom'; import ReactDOM from 'react-dom'; import axios from 'axios'; // 原代码漏了导入axios,需补充 import '../../sass/HomePage/homePage.scss'; import LoginRegister from "./LoginRegister/LoginRegister"; import Gallery from "./Gallery/Gallery"; import Cookies from 'js-cookie'; const App = () => { const [uploadsData, setUploadsData] = useState([]); const { push } = useHistory(); const authToken = Cookies.get('token'); // 用useCallback包裹请求函数,明确声明依赖 const getUploads = useCallback(async () => { // 提前判断登录状态,避免发起无效请求 if (!authToken) { console.log("User's NOT authenticated, returning to login view"); push('/'); return; } try { const headers = { "Accept": 'application/json', "Authorization": `Bearer ${authToken}` } const resp = await axios.get('http://localhost:8005/api/get-uploads', {headers}); // 用函数式更新state,避免依赖外部的uploadsData变量 setUploadsData(prev => [...prev, ...resp.data]); push('/gallery'); } catch (error) { console.log(error); } }, [authToken, push]); // 声明所有用到的外部依赖项 useEffect(() => { getUploads(); }, [getUploads]); // 依赖改为被useCallback包裹的getUploads,仅在依赖变化时重新执行 return ( <> <Switch> <Route exact path="/" component={LoginRegister} /> {/* 用render属性传递props,避免组件反复卸载挂载 */} <Route render={() => <Gallery data={uploadsData}/>} /> </Switch> </> ); } export default App; if (document.getElementById('example')) { ReactDOM.render(<Router><App/></Router>, document.getElementById('example')); }
2. 修复Gallery.js参数接收
import React from 'react'; // 解构props拿到data属性 const Gallery = ({data}) => { return ( <> {console.log(data)} </> ); } export default Gallery;
额外优化建议
- 可新增加载状态,请求未完成时给Gallery展示加载提示,避免空数据闪屏
- 接口异常时增加错误提示,引导用户重试
- 可将authToken存入useState监听变化,避免Cookie更新时组件感知不到
内容的提问来源于stack exchange,提问作者sp92
相关产品推荐
相关产品推荐

