如何在状态转换之前暂停组件的延迟

How to pause the delay of a component before state transition?

本文关键字:暂停 组件 延迟 状态 转换      更新时间:2023-09-26

在呈现页面之前,我有一组AJAX请求要调用。我用的是react-router 2.4.1。在我之前的一个项目中,使用了一个旧版本的react-router,这是我用来处理这个问题的方法,然后

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中实现相同的功能?

你可以尝试使用路由器提供的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);
}

在你的例子中,你可以使用组件而不是require属性。只需将map函数改为返回那个。所以这一行

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

会被改成

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

这只是一个想法,我粘贴的代码只是我使用的设置的简化版本。我目前的设置与Redux绑定,我试图删除示例中关于Redux的所有引用,这就是为什么它可能不太有意义。我也使用同构渲染,所以我的处理程序有点复杂,我不需要客户端上的回调,因为redux将处理重新渲染一旦依赖被获取。

但是你得到了基本的想法。你需要使用onEnter钩子。在那里,您可以获取所有依赖项,并在完成后调用回调函数。它就像你以前的设置,但组织方式略有不同。