Home > Article > Web Front-end > The difference between setState in React and Preact
Preact is a lightweight implementation of React and one of the better alternatives to React. It has the advantage of small size. Of course, there will be implementation differences between it and React. This article introduces the differences in setState. at.
First, let’s analyze the specific implementation of the setState part of React and Preact.
(It’s too long and you want to be lazy, you can just scroll down and read the conclusion)
Key code:
// ReactUpdateQueue.jsenqueueSetState: function(publicInstance, partialState) { ... var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []); queue.push(partialState); enqueueUpdate(internalInstance);}
You can see that React will not do any processing when setState, and will directly put the changes into a queue specifically for processing state for use when components are updated.
// ReactCompositeComponent.jsupdateComponent: function( transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext,) { var inst = this._instance; ... var willReceive = false; var nextContext; if (this._context === nextUnmaskedContext) { nextContext = inst.context; } else { nextContext = this._processContext(nextUnmaskedContext); willReceive = true; } var prevProps = prevParentElement.props; var nextProps = nextParentElement.props; if (prevParentElement !== nextParentElement) { willReceive = true; } if (willReceive && inst.componentWillReceiveProps) { ... inst.componentWillReceiveProps(nextProps, nextContext); } // 在此处才计算 nextState var nextState = this._processPendingState(nextProps, nextContext); // 此处传入了 nextProps var shouldUpdate = true; if (!this._pendingForceUpdate) { if (inst.shouldComponentUpdate) { ... shouldUpdate = inst.shouldComponentUpdate( nextProps, nextState, nextContext, ); } else { if (this._compositeType === CompositeTypes.PureClass) { // 敲黑板,知识点 —— 如果你的组件没实现shouldComponentUpdate,那么把React.Component 换成 React.PureComponent 可以获得基础版优化,提高性能。 shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState); // 浅比较,可以抄去自己改成属性黑/白名单版 } } } ...}// ReactCompositeComponent.js_processPendingState: function(props, context) { // props: nextProps var inst = this._instance; var queue = this._pendingStateQueue; var replace = this._pendingReplaceState; this._pendingReplaceState = false; this._pendingStateQueue = null; if (!queue) { return inst.state; } if (replace && queue.length === 1) { return queue[0]; } var nextState = Object.assign({}, replace ? queue[0] : inst.state); for (var i = replace ? 1 : 0; i < queue.length; i++) { var partial = queue[i]; Object.assign( nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) // nextProps : partial, ); } return nextState;}
You can see through the process code of the above component update:
In updateComponent , nextState is calculated after componentWillReceiveProps, so setState in componentWillReceiveProps can take effect in the current update.
In _processPendingState, the state in the queue will be superimposed. If the modification is in function mode, the state parameter passed here is nextState, and the props are nextProps.
Key code:
##
// component.jssetState(state, callback) { let s = this.state; if (!this.prevState) this.prevState = extend({}, s); extend(s, typeof state==='function' ? state(s, this.props) : state); if (callback) (this._renderCallbacks = (this._renderCallbacks || [])).push(callback); enqueueRender(this);}Simple implementation Rough, the merge is done during setState, this.state will be rewritten immediately, and the state will be retained in prevState during the first setState. Since the state is merged immediately, if the input parameter state is a function, the props will be the current this.props. Update phase:
export function renderComponent(component, opts, mountAll, isChild) { ... previousProps = component.prevProps || props, previousState = component.prevState || state, previousContext = component.prevContext || context, ... // if updating if (isUpdate) { component.props = previousProps; component.state = previousState; component.context = previousContext; if (opts!==FORCE_RENDER && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === false) { skip = true; } else if (component.componentWillUpdate) { component.componentWillUpdate(props, state, context); } component.props = props; component.state = state; component.context = context; } ...}The old state is extracted before the update process, and shouldComponentUpdate and componentWillUpdate are restored back to the new value, so in the shouldComponentUpdate life cycle, What this.props will get is prevProps, which is inconsistent with the logic of React. EmphasisSame point:
not be applied to nextState, but the incoming nextState can be directly manipulated.
But, before updating the component's life cycle to render (eg: shouldComponentUpdate), this.state will be prevState.
The above is the detailed content of The difference between setState in React and Preact. For more information, please follow other related articles on the PHP Chinese website!