简体   繁体   English

React router 4:如何在Route的render方法中等待promise的解析?

[英]React router 4: How to wait for a promise to resolve, inside render method of Route?

I'm trying to achieve functionality, where each Route will first wait for some ajax promise to resolve, and only then will render the route. 我正在尝试实现功能,其中每个Route将首先等待一些ajax承诺解决,然后才会呈现路由。 I saw that onEnter doesn't exist anymore, so i'm trying the render method. 我看到onEnter不再存在,所以我正在尝试渲染方法。

My routes are defined like that: 我的路线定义如下:

{cmsRoutes.map((route, idx) => {
              console.log(route.resolve)
              return route.component ? (<Route  key={idx} path={route.path} exact={route.exact} name={route.name} render={props =>{
               route.resolve()
               .then(({data})=>{
                 console.log(data)
                  return (
                <route.component {...props} />
              )
                }) 

              } } />)
                : (null);
            },
            )}

As you can see, it just iterates over some array, that holds the data for each route. 正如您所看到的,它只是迭代某个数组,它保存每个路由的数据。 One of the fields of the route object is "resolve", which points to a function, that returns a promise. 路由对象的一个​​字段是“resolve”,它指向一个返回promise的函数。 Like this one: 像这个:

const resolvemanageContactApplications = ()=> {
  return ajax('/contact')
};

When executing this, i get the following error: 执行此操作时,我收到以下错误:

Route(...): Nothing was returned from render. 路线(...):渲染没有返回任何内容。 This usually means a return statement is missing. 这通常意味着缺少return语句。 Or, to render nothing, return null. 或者,为了不渲染,返回null。

This of course happens, because while the ajax is being executed, nothing is returned from the route. 这当然会发生,因为在执行ajax时,路由没有返回任何内容。 The question: how can i make React router 4 wait for the promise resolution? 问题是:如何让React路由器4等待承诺解析? There has to be some way. 必须有某种方式。 I remember that AngaulrJS UI-Router actually had some "resolve" api. 我记得AngaulrJS UI-Router实际上有一些“解决”api。

You need another approach here. 你需要另一种方法。

You should use a state to store if your ajax is done or not. 如果你的ajax完成了,你应该使用一个状态来存储。 Then, to render the route you can render nothing (null or ...loading) if the ajax isn't done, and render the actual component or whatever you want with the result of the ajax. 然后,为了渲染路径,如果未完成ajax,则可以不渲染任何内容(null或... loading),并使用ajax的结果渲染实际组件或任何您想要的内容。

I can see you are generating the routes based on an array of data, and to achieve that I would create a Component to wrap the data-loading condition. 我可以看到你正在基于一组数据生成路由,为了实现这一点,我将创建一个Component来包装数据加载条件。 It could receive as props: 它可以作为道具接收:

  • The resolve (the ajax function) 决心(ajax功能)
  • The component to render 要渲染的组件

On the componentDidMount and componentDidUpdate do the ajax call and set the state.waitingResolve to true, and on the .then() of the resolve, set the state.waitingResolve to false, and store the returned data to the state too. 在componentDidMount和componentDidUpdate上执行ajax调用并将state.waitingResolve设置为true,并在resolve的state.waitingResolve .then()上,将state.waitingResolve设置为false,并将返回的数据也存储到状态。

On the render, you check if state.waitingResolve , and renders null (or ...loading) or the component to render that you received from props. 在渲染上,您检查state.waitingResolve ,并渲染null(或... loading)或渲染您从props收到的组件。

It may look like complicated but it is worth. 它可能看起来很复杂但值得。

You can create some async component wrapper like: 您可以创建一些异步组件包装器,如:

class AsyncComponent extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      Component: null
    };
  }

  componentDidMount() {
    const { componentPromise } = this.props;
    componentPromise.then(component => this.setState({
      Component: component
    }));
  }

  render() {
    const { Component } = this.state;

    if (!Component) {
      return null; // You can return some spinner here
    }

    return (
      <Component {...this.props} />
    );
  }
}

And use it inside of your router: 并在路由器中使用它:

<Route
  key={idx}
  path={route.path}
  exact={route.exact}
  name={route.name}
  render={props => (
    <AsyncComponent componentPromise={route.resolve} {...props} />
  )}
/>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM