Maison > interface Web > js tutoriel > le corps du texte

La différence entre setState dans React et Preact

一个新手
Libérer: 2017-10-24 09:34:28
original
1916 Les gens l'ont consulté

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);}
Copier après la connexion

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;}
Copier après la connexion

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);}
Copier après la connexion

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;
  }
  ...}
Copier après la connexion

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!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!