Khan/react-components

StateFromStore misses store changes between getInitialState and componentDidMount

Closed this issue · 3 comments

The problem seems to be that getInitialState brings state into a component, but addChangeListeners is not called until the component is mounted. This can lead to inconsistent state.

For example:

  1. Store initialized with Store._isLoading = false
  2. View component brings in this.state.isLoading = false using StateFromStoreMixin
  3. An AJAX request starts, setting Store._isLoading = true. Store has no change listeners
  4. View component gets mounted, and added as a change listener to Store
  5. AJAX request completes, setting Store._isLoading = false. Listeners are notified
  6. View component rerenders.

What I'd like is for the view component to be added as a change listener to Store at the same time its initial state is loaded, so that we don't miss changes in step 3.

Adding this.setState(this.getInitialState()); to componentDidMount fixed this.

Thanks for the report! Your description was very clear!

@bradencanderson It's not possible for an AJAX request to return between getInitialState and componentDidMount because those two methods are called synchronously in the same tick, so you must be seeing something else. Can you clarify?

Yep, the issue is with synchronous state mutations. What I'm doing here is setting a flag in a Store to keep track of whether an AJAX request is ongoing. So when a component gets its initial state using StateFromStore it requests state from a DataStore, which in turn sends a message 'request_data' over the flux dispatcher. Two Stores read this message -- (1) DataStore (which dispatches the AJAX request asynchronously), and (2) ViewStore (which updates its _isLoading flag synchronously). Some view components depend on ViewStore, and should re-render when ViewStore._isLoading is set to true.

The issue is that I'm doing some synchronous state mutations between getInitialState() and when a component actually gets mounted.

Hopefully that clarifies.

@zgotsch's PR fixes my issue.