Express.js向React.js传数据时数据闪跳、未按指定路由触发请求问题求解
问题根因
页面内容快速切换的原因
- 你的自定义Hook
useFetchData中定义了两个无依赖项的useEffect,这两个副作用会在组件首次渲染完成后同时触发,/api和/s两个请求并行发送,哪个请求先返回就会先调用setData更新状态,后返回的请求会再次覆盖data的值,因此你会看到页面内容快速切换。
请求未在进入/home路由才触发的原因
- 当前你的React应用没有配置前端路由,写的
App是全局根组件,只要服务端返回了React的静态资源,不管当前访问的是什么路径,App组件都会直接渲染,对应的useFetchData里的请求自然会直接触发,不会等待进入/home路径才执行。 - 另外你注释了Express服务端的
*通配符路由,现在直接访问mywebsite.com/home只会得到404错误,根本不会返回React应用页面。
修正方案和相关概念
1. 配置前端路由
你需要使用react-router-dom实现前端路由,把对应路径和页面组件绑定,只有访问对应路径时才会渲染对应组件、触发数据请求:
# 先安装依赖 npm install react-router-dom
调整代码结构示例:
// App.jsx 根组件只做路由分配 import { BrowserRouter, Routes, Route } from 'react-router-dom' import Home from './pages/Home' const App = () => { return ( <BrowserRouter> <Routes> <Route path="/home" element={<Home />} /> {/* 其他路径路由在这里补充 */} </Routes> </BrowserRouter> ) } export default App
// pages/Home.jsx 首页组件,数据请求写在这里 import { useEffect, useState } from 'react' const Home = () => { const [postList, setPostList] = useState([]) // 只有访问/home路径,组件渲染后才会触发该请求 useEffect(() => { // 建议单独封装拉取所有帖子的接口,不要多请求覆盖同一个状态 fetch('/api/posts') .then(res => res.json()) .then(data => setPostList(data)) }, []) return ( <div> {postList.map((post, idx) => ( <div key={idx}> <label className='username'>用户:{post.user}</label> <br/> <label className='body'>帖子内容:{post.body}</label> </div> ))} </div> ) } export default Home
2. 调整服务端路由
打开之前注释的通配符路由,确保所有非接口请求都返回React应用的入口文件,前端路由才能正常工作:
// server/index.js 调整通配符路由 app.get('*', (req, res) => { res.sendFile(path.resolve(__dirname, '../facebook-clone/build', 'index.html')); });
后续你可以新增/api/posts接口,对接数据库查询所有帖子的逻辑即可。
3. 异步请求注意事项
不要把多个接口的返回结果写入同一个状态,若确实需要同时请求多个接口,要么给每个接口分配单独的状态,要么用Promise.all等待所有请求返回后再统一更新状态,避免出现内容来回闪烁的问题。
内容的提问来源于stack exchange,提问作者Zeyad Alaa Eldin
相关产品推荐
相关产品推荐

