ホームページ  >  記事  >  ウェブフロントエンド  >  React と Preact の setState の違い

React と Preact の setState の違い

一个新手
一个新手オリジナル
2017-10-24 09:34:281920ブラウズ

Preact は React の軽量実装であり、React のより優れた代替手段の 1 つです。もちろん、React との実装の違いはあります。この記事では setState の違いを紹介します。

ソースコード分析

まず、React と Preact の setState 部分の具体的な実装を分析しましょう。

(長すぎるのでダラダラしたい場合は、下にスクロールして結論を​​読んでください)

React

キーコード:

setState stage:


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

  enqueueUpdate(internalInstance);}

Reactでは実行できないことがわかりますsetState 中のすべての処理は、コンポーネントの更新時に使用するために、処理状態専用のキューに直接配置されます。

更新ステージ:


// 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 === &#39;function&#39;
        ? partial.call(inst, nextState, props, context) // nextProps
        : partial,
    );
  }

  return nextState;}

上記のコンポーネント更新の処理コードからわかります:

  • updateComponentでは、componentWillReceivePropsの後にnextStateが計算されるため、componentWillReceivePropsのsetStateは現在の更新有効で使用できます。

  • _processPendingState では、変更が関数モードの場合、ここで渡される状態パラメーターは nextState で、プロパティは nextProps です。

Preact

キーコード:

setState ステージ:


// component.jssetState(state, callback) {
  let s = this.state;
  if (!this.prevState) this.prevState = extend({}, s);
  extend(s, typeof state===&#39;function&#39; ? state(s, this.props) : state);
  if (callback) (this._renderCallbacks = (this._renderCallbacks || [])).push(callback);
  enqueueRender(this);}

実装はシンプルで粗雑ですが、setState 中にすぐに書き換えられ、最初の setState 中に保持されます。 state 状態を prevState にします。状態はすぐにマージされるため、入力パラメーターの 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;
  }
  ...}

古い状態は更新プロセスの前に抽出され、 shouldComponentUpdate とcomponentWillUpdate は新しい値に復元されます。 したがって、 shouldComponentUpdate ライフサイクルでは、 this.props は一貫性のある prevProps を取得します。 Reactのロジックと一貫性がありません。

強調

同じ点:

  • componentWillReceiveProps の setState は nextState に適用されます。 shouldComponentUpdate の

  • setState は nextState には適用されませんが、受信した nextState は直接操作できます。

    違い:

React の setState の値はすぐには有効になりませんが、componentWillReceiveProps まで蓄積され、その後マージされて後続のライフサイクルに提供されます。 Preact では、setState はすぐに this.state に反映されますが、
    、レンダリングするコンポーネントのライフサイクルを更新する前 (例: shouldComponentUpdate)、this.state は prevState になります。
  • shouldComponentUpdate ステージの setState は最終的な状態の値には影響しませんが、後でのComponentWillUpdate の this.state など、Preact の this.state の値には影響します。ステージ。

  • setState 関数を使用して変更する場合、Preact で渡される props は prevProps になりますが、React では、componentWillReceiveProps の setState に注意してください。

  • 概要

  • 作成するプロジェクトが React と Preact の両方と互換性がある必要がある場合:

同じコンポーネントの更新が実行される直前に状態が更新されないという React の setState の機能を使用しないでください。それらの間に複数の setState があるかどうかに注意し、必要に応じて古い値を手動で保存します。

  • コンポーネント更新ライフサイクルでは、componentWillReceiveProps 以外の setState を使用しないでください。 nextState ライフサイクルが提供され、nextState を直接変更できます。

  • setState 関数の変更メソッドの使用を避けてください。componentWillReceiveProps で使用する場合は、ライフサイクルで prevProps(this.props) と nextProps を使用してください。

  • 追記: antd-mobile 2.0 の正式版がリリースされました。これは、react および preact とも互換性があり、軽量で高速で使いやすいモバイル コンポーネント ライブラリです。ポータル]

以上がReact と Preact の setState の違いの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。