facebook/react — pull request #1965 by spicyj (2014-07-30 22:17:58+00:00)
Title: Refactor composite component update flow

Fixes #1392.

Previously, ReactComponent.updateComponent set the new props and owner and updated the component's refs. Because it did the actual props assignment, it had to be called by ReactCompositeComponent between componentWillMount and componentDidMount, meaning that it was skipped if shouldComponentUpdate returned false. Now, updateComponent takes the old and new descriptors and only updates refs, allowing a subclass to call updateComponent at a convenient time (specifically, it can be before `this._descriptor` is updated if the subclass also overrides performUpdateIfNecessary).

The new update cycle for composites is:

- receiveComponent is called which stores `this._pendingDescriptor` and calls performUpdateIfNecessary directly or a state update is enqueued, in which case ReactUpdates will call performUpdateIfNecessary
- performUpdateIfNecessary ensures that an update is still pending (which might no longer be the case if an update is queued for a subcomponent that was updated through a parent's reconciliation) and calls updateComponent with the old and new descriptors
- updateComponent calls super to update refs, then calls componentWillReceiveProps (if applicable) and shouldComponentUpdate -- if shouldComponentUpdate returns false, `this._descriptor`, `this.props`, and `this.state` are updated and the update is skipped; else, _performComponentUpdate is called
- _performComponentUpdate calls componentWillUpdate and _updateRenderedComponent, and enqueues the componentDidUpdate call (in that order)
- _updateRenderedComponent calls render and updates the rendered component appropriately

For DOM components (essentially unchanged):

- receiveComponent is called which does a short-circuit check for descriptor equality and delegates to super (which stores `this._pendingDescriptor` and calls performUpdateIfNecessary)
- performUpdateIfNecessary (not overridden) sets new values for `this.props`, etc. and calls updateComponent
- updateComponent does the DOM property and children updates (some synchronously, some queued for the transaction close)

For text and ART components (unchanged):

- receiveComponent updates the DOM or ART directly based on the new props
- updateComponent is never called

Notable changes:

- When shouldComponentUpdate returns false, refs are still updated
- ReactDefaultPerf now includes lifecycle methods in component timings
- updateComponent's signature changed (technically this is part of the public API, though we've never documented it)

Test Plan: jest