1

In react-router, is there any way to pass a property from the Route-definition that can be picked up within the Router.run function? I want specific actions to fire for specific routes. Something like this perhaps:

<Route handler={someComponent} resolve={someAction} />

In Router.Run i want to execute that given action defined in resolve. Is there any way of doing that?

The reason for doing this is to make sure that each route can instantiate service-calls (from a defined action) to make sure that the stores have the data needed for that route. Doing it in the component is also a possibility, the problem we have now is that several components within the same route needs the same data, making it requesting data from the API several times, and also triggering rerendering for each result comming in from those calls.

thsorens
  • 1,308
  • 12
  • 21

1 Answers1

1

You can do something like this in React Router by adding a static (using createClass) or a property on the component class (when using ES6 classes) and then executing them with React Router.

var Component1 = React.createClass({
  statics: fetchData: function(params) {
    return API.getData(params);
  },

  // ...
});

class Component2 extends React.Component {
  // ...
}

Component2.fetchData = (params) => API.getData(params);

Then, when you run your router, look for all matched routes that have a fetchData static method and call it. We'll assume here that fetchData (and thus API.getData) returns a Promise:

Router.run(routes, function(Root, state) {
  var data = {};

  var routesWithFetchData = state.routes.filter(function (route) {
    return route.handler.fetchData
  });

  var allFetchDataPromises = routesWithFetchData.map(function (route) {
    return route.handler.fetchData(state.params).then(function (routeData) {
      data[route.name] = routeData;
    });
  });

 Promise.all(allFetchDataPromises).then(function() {
    React.render(<Root data={data} />, container);
  });
});

(See this React Router example for more details.)

You can solve the "multiple components fetch the same data" problem by ensuring that the API module will catch requests for the same data and assign them the same promise. Pseudocode:

API = {
  getData: function(params) {
    if (requests[params]) {
      return requests[params];
    } else {
      request[params] = new Promise(function(resolve, reject) {
        // fetch data here
      });
    }
  }
};
Michelle Tilley
  • 157,729
  • 40
  • 374
  • 311
  • Its not necessarily promises or servicecalls being triggered, but i see your point. Will extending it make it possible to add something (action or some other prop) directly to the route markup? Since every route needs the possibility to fire their own actions. Like my example with – thsorens Jun 10 '15 at 16:42
  • @thsorens I'm not sure additional properties on `` do anything at all (in fact I can't see that they're even persisted anywhere). – Michelle Tilley Jun 10 '15 at 16:50
  • Ill give you the correct answer, though it didnt entirely solve what i needed, i guess the restrictions lies within the react-router library. Youre solution would probably work though, even though its a bit different approach:) – thsorens Jun 10 '15 at 16:55