[英]Server Side React Initial Render causes duplicated async calls
我在服務器上使用 react-router 2.0。 我的一些頂級路由組件依賴於要獲取的異步數據並使用 Redux 來管理狀態。 為了解決這個問題,我使用了一個靜態的fetchData()
方法來返回一個Promise.all
的異步操作,如官方 Redux 文檔中所建議的。 它工作得很好——來自服務器的初始渲染帶有 Redux 存儲中的適當數據。
我的問題來自如何編寫這些異步調用,這種方式既適用於服務器上的初始渲染,又適用於客戶端上的后續渲染,因為加載了不同的路由。 目前,我在頂級組件的componentDidMount()
調用靜態fetchData()
方法,但是一旦組件安裝在客戶端上,這將導致fetchData()
。 這是我從另一個導航到路由時想要的,但不是在初始渲染時,因為我們已經在服務器上進行了這個調用。
我一直在努力以一種方式編寫我的數據獲取邏輯:
我正在考慮將像{ serverRendered: true }
這樣的道具注入初始組件,但在調用renderToString()
時我只能訪問<RouterContext>
。 我查看了源代碼,但似乎我也無法從該 JSX 標記傳遞該屬性。
我想我的問題是:
<RouterContext>
注入一個屬性,以便它向下傳遞到“父”頂級路由組件? 如果不在<RouterContext>
,是否有另一種方法可以注入該屬性?fetchData()
以便初始渲染不會導致fetchData()
在服務器和客戶端上都被調用?我遇到了同樣的問題。 使用setTimeout
清除某些全局值或檢查 Redux 存儲中是否存在數據對我來說並不好。
我決定檢查加載了哪些路徑初始數據,將此數組作為全局值並檢查componentDidMount
路由匹配。
我的服務器 index.js
const pathsWithLoadedData= []; // here I store paths
const promises = matchRoutes(Routes, req.path)
.map(({ route }) => {
if (route.loadData) {
// if route loads data and has path then save it
route.path && pathsWithLoadedData.push(route.path);
return route.loadData(store);
} else {
return Promise.resolve(null);
}
})
我的渲染模板
<body>
...
<script>
window.INITIALLY_LOADED_PATHS = ${JSON.stringify(pathsWithLoadedData)};
</script>
...
</body>
一些 componentDidMount 函數
componentDidMount () {
if (!wasFetchedInitially(this.props.route.path)) {
this.props.fetchUsers();
}
}
和幫手
export const wasFetchedInitially = componentPath => {
const pathIndex = window.INITIALLY_LOADED_PATHS.indexOf(componentPath);
if (pathIndex < 0) return false;
window.INITIALLY_LOADED_PATHS.splice(pathIndex, 1);
return true;
};
我注入一個全局變量window.__INITAL_FROM_SERVER__ = true
並從客戶端使用setTimeout
清除它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.