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:
- Store initialized with
Store._isLoading = false
- View component brings in
this.state.isLoading = false
using StateFromStoreMixin - An AJAX request starts, setting
Store._isLoading = true
. Store has no change listeners - View component gets mounted, and added as a change listener to Store
- AJAX request completes, setting
Store._isLoading = false
. Listeners are notified - 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.