Ad

Where And How To Request Data Asynchronously To Be Passed Down As Props With React Router (v 1)

- 1 answer

After reading many questions regarding this topic I am still unsure as to which is the best way to asynchronously fetch data which later will be passed down as props to the child routes with React Router v1.0.0 and up.

My route config looks something like this:

import { render } from 'react-dom';
// more imports ...

...

render(
  <Router>
  <Route path="/" component={App} />
    <IndexRoute component={Dashboard}/>
    <Route path="userpanel" component={UserPanel}/>
  </Router>,
  document.getElementById('container')
)

In my App component I have code which asynchronously fetches data from the backend and will incorporate it into its state, if fetching was successful. I use componentDidMount for this within App.

The state of App will look like this contrived example:

{
  user: {
    name: 'Mike Smith',
    email: '[email protected]'
  }
}

I would want to pass the user part of state as props to my IndexRoute and the userpanel route. However I am not sure how I should do this.

A few questions come to mind:

  1. Should I place the async data request somewhere else within my code?
  2. Should I use the React Router api (like onEnter) instead of React lifecycle methods for the data fetching?
  3. How can I pass the state (user) of App to the Dashboard and UserPanel components as props?
  4. I am unsure how to do this with React.cloneElement as seen in other answers.

Thanks for the help in advance.

Ad

Answer

What you are asking for is persistent data between routes and that's not the job of the router.

You should create a store (in flux terms), or a model/collection (in MVC terms) - the usual approach with react is something flux-like. I recommend redux.

In the redux docs it has an example of fetching a reddit user:

componentDidMount() {
  const { dispatch, selectedReddit } = this.props
  dispatch(fetchPostsIfNeeded(selectedReddit))
}

Personally I don't think flux/redux is the easiest approach to implement, but it scales well. The essential concept is even if you decide to use something else:

  • You are correct, as Facebook suggests, async fetching goes best in componentDidMount.

If you want to integrate with other JavaScript frameworks, set timers using setTimeout or setInterval, or send AJAX requests, perform those operations in this method.

  • Next you need to set this data in a store/model which can be accessed from other components.

The nice thing about redux (with react-redux) is that for each component you can say "Here are the actions this component is interested in" and then that component can simply call the action like UserActions.fetchUserIfNeeded() and the action will figure out whether it already has the user or if it should be fetched, and afterwards it will re-render and the prop will be available.

Answer to Q4: What are you trying to clone and why? If it's a child see this answer.

Ad
source: stackoverflow.com
Ad