Maison  >  Article  >  interface Web  >  La différence entre setState dans React et Preact

La différence entre setState dans React et Preact

一个新手
一个新手original
2017-10-24 09:34:281917parcourir

Preact est une implémentation légère de React et l'une des meilleures alternatives à React. Elle présente l'avantage d'être de petite taille. Bien sûr, il doit y avoir des différences d'implémentation entre elle et React.

Analyse du code source

Tout d'abord, analysons l'implémentation spécifique de la partie setState de React et Preact.

(C'est trop long et vous voulez être paresseux, vous pouvez simplement faire défiler vers le bas et lire la conclusion)

Réagir

Code clé :

setState stage :


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

  enqueueUpdate(internalInstance);}

Vous pouvez voir que React n'effectuera aucun traitement lorsque setState et mettra directement les modifications dans une file d'attente spécifiquement pour le traitement de l'état à utiliser lorsque les composants sont mis à jour.

Étape de mise à jour :


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

Vous pouvez voir à travers le code du processus de mise à jour du composant ci-dessus :

  • Dans updateComponent, nextState est calculé après ComponentWillReceiveProps, donc setState dans ComponentWillReceiveProps peut prendre effet dans la mise à jour actuelle.

  • Dans _processPendingState, l'état dans la file d'attente sera superposé. Si la modification est en mode fonction, le paramètre d'état passé ici est nextState, et les accessoires sont nextProps.

Preact

Code clé :

étape 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);}

Implémentation C'est simple et brut. Il est fusionné pendant setState et this.state sera réécrit immédiatement lorsque setState est défini pour la première fois, l'état sera conservé dans prevState. Étant donné que l'état est fusionné immédiatement, si le paramètre d'entrée state est une fonction, les accessoires seront les this.props actuels.

Phase de mise à jour :


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

L'ancien état est extrait avant le processus de mise à jour, et devraitComponentUpdate et composantWillUpdate sont restaurés à la nouvelle valeur après cela, donc dans le cycle de vie ShouldComponentUpdate, this.props obtiendra prevProps, ce qui est incompatible avec la logique de React.

Emphase

Même point :

  • setState dans composantWillReceiveProps sera appliqué à nextState.

  • setState dans ShouldComponentUpdate ne sera pas appliqué à nextState, mais le nextState entrant peut être directement manipulé.

Différences :

  • La valeur de setState sous React ne prendra pas effet immédiatement et s'accumulera jusqu'à composantWillReceiveProps, après quoi elle sera fusionnée . Et fournissez-le aux cycles de vie ultérieurs. Sous Preact, setState sera immédiatement reflété dans this.state, mais , avant de mettre à jour le cycle de vie du composant pour le rendu (par exemple : ShouldComponentUpdate), this.state sera prevState.

  • Bien que setState dans l'étape ShouldComponentUpdate n'affectera pas la valeur de l'état final, cela affectera la valeur de this.state sous Preact, comme this.state dans ComponentWillUpdate plus tard. , ne définissez pas State à ce stade, c'est inutile de toute façon.

  • setState Si vous utilisez une fonction pour la modifier, les accessoires transmis sous Preact seront prevProps, mais nextProps dans React Faites attention lors du réglage de State dans composantWillReceiveProps.

Résumé

Si le projet que vous écrivez doit être compatible à la fois avec React et Preact :

  • Ne pas utiliser setState sous React. L'état n'est pas mis à jour immédiatement avant l'exécution de la même mise à jour du composant. Faites attention s'il y a une influence entre plusieurs setStates et enregistrez les anciennes valeurs manuellement si nécessaire.

  • Pendant le cycle de vie de mise à jour du composant, n'utilisez pas setState sauf composantWillReceiveProps Le cycle de vie nextState est fourni et nextState peut être modifié directement.

  • Essayez d'éviter d'utiliser la méthode de modification de la fonction setState. Lorsque vous l'utilisez dans composantWillReceiveProps, utilisez prevProps(this.props) et nextProps dans le cycle de vie.

p.s : La version officielle d'antd-mobile 2.0 a été publiée. Elle est également compatible avec React et Preact. Il s'agit d'une bibliothèque de composants mobiles légère, rapide et facile à utiliser. , en attendant que vous l'utilisiez ~ [Portail 】

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn