Heim  >  Artikel  >  Web-Frontend  >  Der Unterschied zwischen setState in React und Preact

Der Unterschied zwischen setState in React und Preact

一个新手
一个新手Original
2017-10-24 09:34:281943Durchsuche

Preact ist eine einfache Implementierung von React und eine der besseren Alternativen zu React. Es gibt natürlich Unterschiede in der Implementierung zwischen ihm und React.

Quellcode-Analyse

Lassen Sie uns zunächst die spezifische Implementierung des setState-Teils von React und Preact analysieren.

(Es ist zu lang und Sie möchten faul sein, Sie können einfach nach unten scrollen und die Schlussfolgerung lesen)

Reagieren

Tastencode:

setState stage:


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

  enqueueUpdate(internalInstance);}

Sie können sehen, dass React bei setState keine Verarbeitung durchführt und die Änderungen direkt in eine Warteschlange speziell für den Verarbeitungsstatus zur Verwendung bei Komponenten stellt werden aktualisiert.

Aktualisierungsphase:


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

Sie können den Prozesscode der oben genannten Komponentenaktualisierung durchsehen:

  • In updateComponent wird nextState nach ComponentWillReceiveProps berechnet, sodass setState in ComponentWillReceiveProps im aktuellen Update wirksam werden kann.

  • In _processPendingState wird der Status in der Warteschlange überlagert. Wenn sich die Änderung im Funktionsmodus befindet, ist der hier übergebene Statusparameter nextState und die Requisiten sind nextProps.

Preact

Schlüsselcode:

setState-Stufe:


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

Implementierung Es ist einfach und grob. Es wird während setState zusammengeführt und this.state wird sofort neu geschrieben. Wenn setState zum ersten Mal festgelegt wird, bleibt der Status in prevState erhalten. Da der Status sofort zusammengeführt wird und der Eingabeparameter state eine Funktion ist, sind die Requisiten die aktuellen this.props.

Aktualisierungsphase:


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

Der alte Zustand wird vor dem Aktualisierungsprozess extrahiert und sollte danachComponentUpdate und ComponentWillUpdate auf den neuen Wert zurücksetzen. Daher erhält this.props im Lebenszyklus von ShouldComponentUpdate prevProps, was nicht mit der Logik von React vereinbar ist.

Hervorhebung

Gleicher Punkt:

  • setState in ComponentWillReceiveProps wird auf nextState angewendet.

  • setState in ShouldComponentUpdate wird nicht auf nextState angewendet, aber der eingehende nextState kann direkt manipuliert werden.

Unterschied:

  • Der Wert von setState unter React wird nicht sofort wirksam, sondern akkumuliert bis ComponentWillReceiveProps und wird dann zusammengeführt . Und stellen Sie es für nachfolgende Lebenszyklen bereit. Unter Preact wird setState sofort in this.state widergespiegelt, aber , bevor der Lebenszyklus der Komponente zum Rendern aktualisiert wird (z. B. ShouldComponentUpdate), wird this.state prevState sein.

  • Obwohl setState in der Phase „shouldComponentUpdate“ keinen Einfluss auf den Wert des Endzustands hat, wirkt es sich auf den Wert von „this.state“ unter „Preact“ aus, beispielsweise „this.state“ in „componentWillUpdate“ später , setState zu diesem Zeitpunkt nicht. Es ist sowieso nutzlos.

  • setState Wenn Sie eine Funktion zum Ändern verwenden, sind die unter Preact übergebenen Requisiten prevProps, in React jedoch nextProps. Achten Sie beim SettingState in ComponentWillReceiveProps darauf.

Zusammenfassung

Wenn das von Ihnen geschriebene Projekt sowohl mit React als auch Preact kompatibel sein muss:

  • Verwenden Sie setState nicht Unter „Reagieren“ wird der Status nicht unmittelbar vor der Ausführung derselben Komponentenaktualisierung aktualisiert. Achten Sie darauf, ob es einen Einfluss zwischen mehreren setStates gibt, und speichern Sie die alten Werte bei Bedarf manuell.

  • Verwenden Sie setState während des Komponentenaktualisierungslebenszyklus nicht, außer ComponentWillReceiveProps. Der nextState-Lebenszyklus wird bereitgestellt und nextState kann direkt geändert werden.

  • Vermeiden Sie die Verwendung der setState-Funktionsänderungsmethode. Wenn Sie sie in ComponentWillReceiveProps verwenden, verwenden Sie prevProps(this.props) und nextProps im Lebenszyklus.

p.s.: Die offizielle Version von antd-mobile 2.0 ist auch mit React und Preact kompatibel. Es handelt sich um eine leichte, schnelle und benutzerfreundliche Bibliothek für mobile Komponenten , wartet darauf, dass du es verwendest~ [Portal 】

Das obige ist der detaillierte Inhalt vonDer Unterschied zwischen setState in React und Preact. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn