Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. I saw that onEnter doesn't exist anymore, so i'm trying the render method.

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. 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. Or, to render nothing, return null.

This of course happens, because while the ajax is being executed, nothing is returned from the route. The question: how can i make React router 4 wait for the promise resolution? There has to be some way. I remember that AngaulrJS UI-Router actually had some "resolve" api.

like image 289
i.brod Avatar asked Jun 19 '18 12:06

i.brod


Video Answer


1 Answers

You need another approach here.

You should use a state to store if your ajax is done or not. 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.

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. It could receive as props:

  • The resolve (the ajax function)
  • 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.

On the render, you check if state.waitingResolve, and renders null (or ...loading) or the component to render that you received from props.

It may look like complicated but it is worth.

like image 134
Murilo Cruz Avatar answered Sep 29 '22 12:09

Murilo Cruz