最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
当前位置: 首页 - 科技 - 知识百科 - 正文

React与Preact中关于setState的区别

来源:懂视网 责编:小采 时间:2020-11-27 20:11:46
文档

React与Preact中关于setState的区别

React与Preact中关于setState的区别:Preact是React的轻量级实现,是React比较好的替代者之一,有着体积小的优点,当然与React之间一定会存在实现上的差异,本文介绍了在 setState 方面的差异之处。源码分析首先来分析下React以及Preact在setState部分的具体实现。(太长不看想偷懒,可以直接下
推荐度:
导读React与Preact中关于setState的区别:Preact是React的轻量级实现,是React比较好的替代者之一,有着体积小的优点,当然与React之间一定会存在实现上的差异,本文介绍了在 setState 方面的差异之处。源码分析首先来分析下React以及Preact在setState部分的具体实现。(太长不看想偷懒,可以直接下

Preact是React的轻量级实现,是React比较好的替代者之一,有着体积小的优点,当然与React之间一定会存在实现上的差异,本文介绍了在 setState 方面的差异之处。

源码分析

首先来分析下React以及Preact在setState部分的具体实现。

(太长不看想偷懒,可以直接下翻看结论)

React

关键代码:

setState 阶段:

// ReactUpdateQueue.jsenqueueSetState: function(publicInstance, partialState) {
 ... var queue =
 internalInstance._pendingStateQueue ||
 (internalInstance._pendingStateQueue = []);
 queue.push(partialState);

 enqueueUpdate(internalInstance);}

可以看到React在 setState 的时候不会做任何处理,会把变更直接放到一个专门处理 state 的队列里供组件更新时使用。

更新阶段:

// 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;}

通过上面组件更新的流程代码可以看到:

  • 在 updateComponent 中,在 componentWillReceiveProps 之后才会计算 nextState,所以在 componentWillReceiveProps 中 setState 是可以在当次更新中生效的。

  • 在 _processPendingState 会对队列里的 state 进行叠加,如果修改是函数方式,此处传入的state参数是 nextState,props 是 nextProps。

  • Preact

    关键代码:

    setState 阶段:

    // 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);}

    实现的简单粗暴,在 setState 的时候就进行了合并,会立即改写 this.state,在第一次 setState 时会保留 state 状态到 prevState。由于是立即合并state,如果入参state是函数,props 将只是当前 this.props。

    更新阶段:

    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;
     }
     ...}

    在更新流程前提取了旧 state,shouldComponentUpdate、componentWillUpdate 之后还原回新值,所以在 shouldComponentUpdate 生命周期中,this.props 将获取的是 prevProps,这里与 React 的逻辑并不一致。

    划重点

    相同点:

  • 在 componentWillReceiveProps 中 setState 都会应用到 nextState。

  • 在 shouldComponentUpdate 中 setState 都不会应用到 nextState,但是可以直接操作传入的 nextState。

  • 不同点:

  • React下 setState 的值不会立即生效,会一直积累到 componentWillReceiveProps,在此之后会进行合并,并提供给后续生命周期。而Preact下 setState 会立即反映到 this.state,但是,在更新组件的生命周期到 render 前(eg: shouldComponentUpdate), this.state 将会是 prevState。

  • shouldComponentUpdate 阶段 setState 虽然不会影响到最终 state 的值,但是Preact下会影响 this.state 的值,比如之后 componentWillUpdate 中的 this.state, 总之此阶段不要 setState 反正也没用。

  • setState 如果使用函数修改,Preact下传入的 props 将会是 prevProps,而React中是 nextProps,在 componentWillReceiveProps 中 setState 时要注意。

  • 总结

    如果你写的工程需要同时兼容React及Preact的话:

  • 不要利用React下 setState 在同一次组件更新执行前 state 不立即更新的特性,注意多个 setState 之间是否影响,必要时手动保存旧值。

  • 在组件更新生命周期内,除 componentWillReceiveProps 之外不要使用 setState,提供了 nextState 的生命周期,可以直接修改 nextState。

  • 尽量避免使用 setState 函数修改方式,在 componentWillReceiveProps 中使用时,使用生命周期中的 prevProps(this.props) 和 nextProps。

  • p.s: antd-mobile 2.0正式版已发布,同时兼容react、preact,轻量、快速、易用的移动端组件库,等你来用~ 【传送门】

    声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文档

    React与Preact中关于setState的区别

    React与Preact中关于setState的区别:Preact是React的轻量级实现,是React比较好的替代者之一,有着体积小的优点,当然与React之间一定会存在实现上的差异,本文介绍了在 setState 方面的差异之处。源码分析首先来分析下React以及Preact在setState部分的具体实现。(太长不看想偷懒,可以直接下
    推荐度:
    标签: React setState react中
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top