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).
componentDidMount
, when he notices that the DOM diverge from it Virtual one, it gives me errors! – Helpless