Dac0d3r
Dac0d3r

Reputation: 1854

Defer rendering of child components until saga completes in parent React component

<Provider store={this.props.store}>
  <ConnectedRouter history={this.props.history}>
    <AppWrap>
      <Header />
      <Main>
        <Switch>
          <Route exact path="/" component={Component1}/>
          <Route path="/component2" component={Component2}/>
        </Switch>
      </Main>
    </AppWrap>
  </ConnectedRouter>
</Provider>

Inside App.componentWillMount, the Redux action this.props.requestApplesApiData is triggered. It is handled by a saga, which fetches some data from an api and returns with another action receiveApplesApiData with a payload, which is added to the redux state by the reducer.

componentWillMount(){
  // triggers an action 
  // which is picked up by a saga, 
  // which is handled by the reducer 
  // which updates the redux state
  this.props.requestApplesApiData();
}

Redux state is updated fine, when I inspect it in the chrome dev tools (w. redux extension), but I noticed that the redux state (with the recently fetched "apples") is not updated in time in Component2, while the race condition was won in Component 1. This means, that Component2 can't display the "apples", because they weren't there at the time of its render function.

A re-render would usually happen automatically, if it was in a nested tree like structure, however "apples" are located in their own root object in the redux store.

How can I have Component1 and Component2 wait for App to fetch the necessary data. Or put in other words, how can I delay/defer the render function in App, until the data is in redux?

Upvotes: 1

Views: 1546

Answers (1)

mef79
mef79

Reputation: 135

Two options:

  • Conditionally render the component based on whether a certain value is present in the store
  • Display something intermediary before the value is updated in the Redux store

But it sounds like the main issue here though is getting the component to update based of a change in the store.

The general path is that components will update when any of their props are updated. Once the saga completes, it will update some value in the redux store. Components should have something that watches the store and updates their props from the store. This is what will tell React to re-render these components. General convention is to store all of these updates in a mapStateToProps function.

Your example is fairly stripped down, so I'm not sure how much of the built in redux functionality you're using, but here are the docs that describe how to pass updated props to your component: https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options

Summary from the docs: connect the component to the store with connect() and the first param needs to be a function specifying how the component will update its props from the store.

Upvotes: 2

Related Questions