簡體   English   中英

服務器端 React Initial Render 導致重復的異步調用

[英]Server Side React Initial Render causes duplicated async calls

我在服務器上使用 react-router 2.0。 我的一些頂級路由組件依賴於要獲取的異步數據並使用 Redux 來管理狀態。 為了解決這個問題,我使用了一個靜態的fetchData()方法來返回一個Promise.all的異步操作,如官方 Redux 文檔中所建議 它工作得很好——來自服務器的初始渲染帶有 Redux 存儲中的適當數據。

我的問題來自如何編寫這些異步調用,這種方式既適用於服務器上的初始渲染,又適用於客戶端上的后續渲染,因為加載了不同的路由。 目前,我在頂級組件的componentDidMount()調用靜態fetchData()方法,但是一旦組件安裝在客戶端上,這將導致fetchData() 這是我從另一個導航到路由時想要的,但不是在初始渲染時,因為我們已經在服務器上進行了這個調用。

我一直在努力以一種方式編寫我的數據獲取邏輯:

  1. 僅在服務器上的初始渲染上調用一次,而不是在客戶端初始渲染上調用
  2. 當用戶從另一條路線導航時將呈現。

我正在考慮將像{ serverRendered: true }這樣的道具注入初始組件,但在調用renderToString()時我只能訪問<RouterContext> 我查看了源代碼,但似乎我也無法從該 JSX 標記傳遞該屬性。

我想我的問題是:

  1. 有沒有辦法在<RouterContext>注入一個屬性,以便它向下傳遞到“父”頂級路由組件? 如果不在<RouterContext> ,是否有另一種方法可以注入該屬性?
  2. 如果#1 不可能,是否有更好的方法來處理fetchData()以便初始渲染不會導致fetchData()在服務器和客戶端上都被調用?

這是我的 server.jsx、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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM