React+Redux+Saga服务端渲染:如何阻止客户端重复Ajax请求?
嘿,我之前也碰到过一模一样的问题!SSR完客户端还重复发请求,既浪费资源又影响体验,结合你用的Node/Express/React + Redux-Saga技术栈,咱们可以从这几个核心点解决:
解决SSR后客户端重复发起Ajax请求的方案
1. 把服务端的Redux状态同步到客户端
服务端渲染时你肯定已经通过saga拿到了页面所需数据,并且填充到Redux store里了对吧?那关键一步就是把这个服务端的store状态序列化后注入到客户端页面。
比如在服务端的HTML模板(比如用EJS/Pug或者直接字符串拼接)里加这段脚本:
<script> window.__INITIAL_STATE__ = <%= JSON.stringify(store.getState()) %> </script>
然后客户端初始化Redux store的时候,直接用这个全局变量作为初始状态:
const initialState = window.__INITIAL_STATE__ || {}; const store = createStore( rootReducer, initialState, applyMiddleware(sagaMiddleware) );
这样客户端的store从一开始就有服务端预取的数据,后续saga就不会因为状态为空去发起请求了。
2. 在Saga里加状态判断,跳过重复请求
就算同步了初始状态,有时候saga还是可能触发请求,这时候要在你的数据获取saga里加个判断:先检查对应状态是否已有数据,有就直接跳过请求。
比如你获取文章列表的saga可以这么写:
function* fetchPostsSaga() { // 先从state里读取已有数据 const existingPosts = yield select(state => state.posts.list); // 如果已有数据,直接返回,不发起请求 if (existingPosts && existingPosts.length > 0) { return; } // 没有数据才调用接口 const response = yield call(api.fetchPosts); yield put(fetchPostsSuccess(response.data)); }
不管是服务端还是客户端触发这个saga,都会先判断状态,彻底避免重复请求。
3. 控制客户端页面初始化的请求触发时机
另外,客户端渲染时,别在组件的useEffect或者componentDidMount里直接触发数据请求的action,而是让saga根据初始状态自动判断是否需要执行。如果用了React Router,服务端已经根据当前路由预取了对应页面的数据,客户端初始化路由时就不需要再触发相同请求了——初始状态里已经有了呀。
总结下来,核心就是让客户端继承服务端的初始状态,再在saga层做数据存在性校验,这样就能完美阻止那些多余的Ajax请求啦。
内容的提问来源于stack exchange,提问作者jsDevia
相关产品推荐
相关产品推荐

