2016-07-02 75 views
1

我有一套AJAX請求在頁面呈現之前被調用。我正在使用react-router 2.4.1。在我以前的項目,所用反應路由器的舊版本中的一個,這是我用來處理這個問題,那麼如何在狀態轉換之前暫停組件的延遲?

Router.run(RouteConfig, function(Handler, state){ 
    var promises = state.routes.filter(function(route) { 
     //Every component that needs initial data for rendering will 
     //define a function fetchData in its statics which will return 
     //a promise that will be resolved once all required AJAX calls    
     //are made. 
     return route.handler.fetchData; 
    }).map(function(route) { 
     return route.handler.fetchData(state.params, state.query); 
    }); 
    if(promises.length > 0) { 
     Promise.all(promises).then(function(response) { 
      data = response; 
      //Rendering will happen only after every call is resolved 
      render(Handler, data); 
     }).catch(function(response, err) { 
      data = response; 
      data.isError = true; 
      data.splice(err.index, 1, err.reason); 
      render(Handler, data); 
     }); 
    } else { 
     render(Handler, data); 
    } 
}); 

function render(Handler, data) { 
    React.render(<Handler data={data}/>, document.body); 
} 

在新版本中,沒有Router.run我明白了。我如何在2.4.1中達到同樣的效果?

回答

2

您可以嘗試使用路由器提供的onEnter掛鉤。我將使用React Router顯示當前的設置。請記住,我聲明瞭路由上的依賴關係而不是組件上的依賴關係,但是您可以根據需要更改該行爲。

採取的路線名單爲例:

<Route path="/" onEnter={fetchDependencies} component={AppContainer}> 
    <IndexRedirect to="/home" /> 
    <Route path="/home" component={StaticContainer} require={loadStaticPage} /> 
    <Route path="/contact" component={StaticContainer} require={loadStaticPage} /> 
</Route> 

添加自己的處理程序頂端路由器獲取每個依賴,對於你只需要設置該屬性onEnter的功能。我也有需要一些依賴關係的路由上的自定義屬性,我將它命名爲prop require,它可以簡單地作爲返回承諾的函數。在你的情況下使用該組件。

這的OnEnter需要一個功能具有以下簽名:

onEnter(nextState, replace, callback?)

回調是可選的,如果提供的路由器不會呈現組件中直到回調被稱爲沒有任何錯誤。這就是你假裝的行爲。

這是我取的依賴關係,你可以適應這個代碼,以滿足您的需要

function fetchDependencies(toRoute, redirect, done) { 
    const { routes, params, location } = toRoute; 
    const payload = Object.assign({}, location, { params }); 
    const promises = routes 
    .map(({ require }) => require) 
    .filter(f => typeof f === 'function') 
    .map(f => f(payload)); 

    return Promise.all(promises).then(() => done() , done); 
} 

你的情況,你可以使用,而不是要求性能的組件。只需更改地圖功能即可返回。所以這條線

.map(({ require }) => require)

將改爲類似

.map(({ component }) => component.fetchData)

這只是一個想法,我已經粘貼代碼設置的只是一個簡化版本,我使用。我目前的設置與Redux綁定,我嘗試刪除每個關於該示例中redux的引用,這就是爲什麼它可能不合理。我也使用同構渲染,所以我的處理程序有點複雜,我不需要客戶端的回調,因爲在獲取依賴關係後,redux將處理重新渲染。

但你得到了基本的想法。你需要玩onEnter鉤子。在完成後,您可以獲取所有依賴關係並調用回調函數。這就像你的舊設置,但組織方式略有不同。

+0

非常感謝@andre .. –