I saw this line as an answer to another question on here:
"componentWillMount should be componentDidMount, or else you'll leak event emitters in node."
and I don't really understand it. Can someone explain with more detail?
More info:
Building a react application with flux, as part of the initial render, a child component computes some data. Ideally, after this data is computed, I would like to call an action that updates the store's state with a portion of this new data.
Normally, updating the store's state emits a change event that causes a re-render. However, because the change listener isn't being added until componentDidMount (rather than in componentWillMount), my top level component isn't able to listen for the change that occurs during the initial render and initiate a re-render.
If I move the addChangeListener to componentWillMount that would seem to fix this issue, but the above quote suggests that this is a bad idea?
I think the prevailing wisdom that listeners should be set in componentDidMount
because it prevents problems in isomorphic applications is a mistake. I think in 98% of cases for non-isomorphic applications setting listeners in either componentWillMount
and componentDidMount
will work the same way, but it is conceptually wrong and in the 2% of cases (such as the example given in the original question) it will do the wrong thing.
There are git issue discussions and comments in the React source code suggesting that it would be preferred that componentWillMount
wasn't called on the server at all, but if it isn't then problems are created in the checksum test comparing the server prerender to the client initial render. Having componentWillMount
on the server means that it isn't executed as part of the component lifecycle in this case, but this is being used as an excuse to not count it as part of the lifecycle in any case.
In fact, componentWillMount
is exactly the right place to register listeners if you are not creating an isomorphic application. If you are creating an isomorphic application then you have to make some compromises due to the checksum/lifecycle issue not being ideal in this case (maybe just testing for the server environment and then not registering listeners?).
In non-isomorphic applications adding listeners in componentWillMount
can save unnecessary re-renders in some cases and will register them in document order. The advantage of document order is that if you have a way to flush pending events as components are re-rendered (for example, takeRecords
on a MutationObserver
) then you can ensure the document is re-rendered top down instead of bottom up, converting the rendering complexity to linear from polynomial.
Additionally, there is no danger period between the initial render and when the listener is registered where the Store can change without triggering a render, causing the view to be out of sync with the Store (the example problem given in the original question). If the listener is registered in componentDidMount
you either need to make sure the Store isn't changed in componentDidMount
calls in children, or else force a re-render/re-sync after registering the listener, which if done in componentDidMount
is done in reverse document order which may be polynomial complexity (depending on how/if the React setStates
are aggregated).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With