A source-code getaway.
Let's explore a simple, perhaps contrived example of a change to a React component with setState, changing a boolean to reflect the display of a form.
Eric Saxman | 'Andrelton' - 2015.
Find me on GitHub | LinkedIn.
Example: this.setState({ showForm: true; });
Many functions are called throughout the course of enqueueing and making changes to the DOM. Perhaps the easiest way of following the series of function calls will be to have a strict understanding which variable caries points to the component and which variable carries the updated state.
For the purpose of this exercise, we'll ignore the callback process and focus solely on the state.
When equeueSetState is called within setState, this is the component, and partialState is the updated state we provided. In subsequent function calls, the component will be referred to as publicInstance.
getInternal... goes out to ReactInstanceMap to retrieve the internal representation of this public-facing stateful instance.
This internal representation is already carried on the component as the property _reactInternalInstance, ReactInstanceMap simply separates the key/value pair and returns the internal instance.
Finally, the internal representation of the component is added to a queue for a potential rerendering.
NOTE: Very little code has been removed. Most sections represented by elipses are error-handling messages which are not present in the minified version.
https://fb.me/react-0.13.3.js
ReactComponent.prototype.setState = function(partialState, callback) { ... ReactUpdateQueue.enqueueSetState(this, partialState); if (callback) { ReactUpdateQueue.enqueueCallback(this, callback); } }; }; var ReactUpdateQueue = { ... enqueueSetState: function(publicInstance, partialState) { var internalInstance = getInternalInstanceReadyForUpdate( publicInstance, 'setState' ); ... enqueueUpdate(internalInstance); }, ... }; function getInternalInstanceReadyForUpdate(publicInstance, callerName) { ... var internalInstance = ReactInstanceMap.get(publicInstance); ... return internalInstance; }; var ReactInstanceMap = { ... get: function(key) { return key._reactInternalInstance; }, ... }; function enqueueUpdate(component) { ... dirtyComponents.push(component); };
var dirtyComponents = []; ... function runBatchedUpdates(transaction) { var len = transaction.dirtyComponentsLength; ... dirtyComponents.sort(mountOrderComparator); for (var i = 0; i < len; i++) { var component = dirtyComponents[i]; ... ReactReconciler.performUpdateIfNecessary( component, transaction.reconcileTransaction ); }; }; var ReactReconciler = { ... performUpdateIfNecessary: function(transaction) { if (this._pendingElement != null) { ReactReconciler.receiveComponent( this, this._pendingElement || this._currentElement, transaction, this._context ); } }, ... receiveComponent: function(nextElement, transaction, nextContext) { var prevElement = this._currentElement; var prevContext = this._context; this._pendingElement = null; this.updateComponent( transaction, prevElement, nextElement, prevContext, nextContext ); }, ... };