Update to match 16.4 gDSFP semantics
Conceptually, getDerivedStateFromProps is like a setState updater function. But it needs to be called after all the other updates in the queue, and it must be called exactly once, right before shouldComponentUpdate.
Other than getDerivedStateFromProps itself, there's no lifecycle that meets these requirements. componentWillReceiveProps fires only if the props have changed. componentWillUpdate fires too late.
This polyfill works by monkeypatching instance.updater. updater is an internal-ish API that has stayed mostly stable across several major versions of React. The polyfill intercepts updates before they are added to the native update queue. Then it schedules a single update with the native update queue, in the form of an updater function. Inside that updater function, the intercepted updates are processed. Finally, getDerivedStateFromProps is called and applied. This approach guarantees that getDerivedStateFromProps is always called at the end.
Note: The polyfill does not attempt to fix React 16.3. Components running in 16.3 will use the native, incorrect behavior. Consumers should upgrade to 16.4.
Unresolved questions:
- Shallow renderer support. The shallow renderer uses
instance.updaterin non-standard ways. As far as I can tell, there's no way to polyfillgetDerivedStateFromPropscorrectly without relying on shallow renderer specific internals likeupdater._invokeCallbacksandinstance._newState. - Limited support for
forceUpdate. BecauseforceUpdatedoes not accept asetStateupdater function,getDerivedStateFromPropswill not be called as a result offorceUpdate, unless it's part of the same batch as asetStateor an update on a parent component.
I'm not sure the benefits of this PR outweigh the costs.
Positives:
- More faithful polyfill for 16.4+
Negatives:
- Loss of support for e.g. Preact, Inferno.
- Increased size and complexity (which may encourage size-conscious people to aim for a cheaper inline polyfill).
- No way to avoid subtle incompatibilities between 16.3 and other versions. (Although to be fair, some form of incompatibility will exist regardless.)
It seems silly to have a polyfill that does not match the "correct" semantics. We are trying to use this with React-Redux 5.1, and we've got a branch with tests that are passing with 16.4 but failing with <= 16.3.
how is this pr going on ? it's really confusing that we need to fix some bugs lower than 16.4 when all tests are passed in 16.4.x.