如何在状态转换前暂停组件的延迟?
How to pause the delay of a component before state transition?
我有一组 AJAX 请求要在页面呈现之前调用。我正在使用反应路由器 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 hooks。我将展示我当前的 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
上设置一个函数。我在需要一些依赖项的路由上也有一个自定义 属性,我将该道具命名为 require
,它可以只是一个 return 承诺的函数。根据您的情况,使用该组件。
这个 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);
}
在您的情况下,您可以使用组件而不是要求 属性。只需将地图功能更改为 return 即可。所以这一行
.map( ({ require }) => require )
会变成类似
的样子
.map( ({ component }) => component.fetchData )
这只是一个想法,我粘贴的代码只是我使用的设置的简化版本。我当前的设置与 Redux 相关,并且我试图删除该示例中所有关于 redux 的引用,这就是为什么它可能没有完全意义。我也使用同构渲染,所以我的处理程序有点复杂,我不需要客户端上的回调,因为 redux 将在获取依赖项后立即处理重新渲染。
但是你已经明白了基本的想法。你需要玩 onEnter 钩子。在那里,您可以获取所有依赖项并在完成后调用回调函数。它就像您的旧设置,但组织方式略有不同。
我有一组 AJAX 请求要在页面呈现之前调用。我正在使用反应路由器 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 hooks。我将展示我当前的 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
上设置一个函数。我在需要一些依赖项的路由上也有一个自定义 属性,我将该道具命名为 require
,它可以只是一个 return 承诺的函数。根据您的情况,使用该组件。
这个 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);
}
在您的情况下,您可以使用组件而不是要求 属性。只需将地图功能更改为 return 即可。所以这一行
.map( ({ require }) => require )
会变成类似
的样子.map( ({ component }) => component.fetchData )
这只是一个想法,我粘贴的代码只是我使用的设置的简化版本。我当前的设置与 Redux 相关,并且我试图删除该示例中所有关于 redux 的引用,这就是为什么它可能没有完全意义。我也使用同构渲染,所以我的处理程序有点复杂,我不需要客户端上的回调,因为 redux 将在获取依赖项后立即处理重新渲染。
但是你已经明白了基本的想法。你需要玩 onEnter 钩子。在那里,您可以获取所有依赖项并在完成后调用回调函数。它就像您的旧设置,但组织方式略有不同。