Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Router wait for resolve

I come from Angular and used to ui-router's resolve capabilities which makes it easy to wait and inject results to controllers.

Currently, I want to mimic this with react without having to write the request (or trigger actions) within the componentWillMount method when using React Router. I think there is a better way to do it, I just haven't figured out what.

Would love to get some advice or point me to where I can learn to do so

like image 668
Mohamed El Mahallawy Avatar asked May 13 '15 06:05

Mohamed El Mahallawy


1 Answers

Your best bet is to use the callback in Router.run (http://rackt.github.io/react-router/#Router.run). The callback you pass to that gets called whenever the url changes, and it's responsible for re-rendering, like this example taken from the page:

Router.run(routes, function (Root) {
  // whenever the url changes, this callback is called again
  React.render(<Root/>, document.body);
});

In that function, you can do any async operations you need before calling React.render(), like this:

Router.run(routes, function (Root) {
  // whenever the url changes, this callback is called again
  asyncStuff().then(function (data) {
    React.render(<Root data={data} />, document.body);
  });
});

The problem with this approach is that your UI won't react at all until that data is available. Instead I would recommend rendering your component with an empty state, and fetching the data in componentDidMount and then re-render when the data comes in. Or even better, separate the data fetching and the rendering into two components. One component fetches the data, and passes that to the rendering component as a property. The data fetching component can even avoid rendering the other component unless the data is there, something like:

render: function () {
  if (this.state.data) {
    return <TheComponent data={this.state.data} />;
  } else {
    return <Spinner />;
  }
}

This is a common pattern in React, to separate components that deals with data fetching and state, and components that render that state. You want to push the stateful components as far up the hierarchy as possible because it creates a logical boundary. The stateful components are where 90% of the bugs occur, and it's nice to be able to focus on those when you're bug hunting.

Another problem with waiting is that the user might navigate quickly, which means that the Router.run callback gets called again before the first data came in. So you need to make sure you abort the last operation and not render that at all.

like image 178
Anders Ekdahl Avatar answered Oct 05 '22 23:10

Anders Ekdahl