477 votes

Découvrez pourquoi un composant React effectue un nouveau rendu.

Existe-t-il une approche systématique pour déboguer ce qui cause la restitution d'un composant dans React? Je mets un simple console.log () pour voir combien de fois il est rendu, mais j'ai du mal à comprendre ce qui provoque le rendu du composant plusieurs fois, c'est-à-dire (4 fois) dans mon cas. Existe-t-il un outil existant qui affiche un plan de montage chronologique et / ou l’arborescence de tous les composants?

508voto

Jacob R Points 3370

Si vous voulez un extrait court sans aucune dépendance externe, je trouve cela utile

 componentDidUpdate(prevProps, prevState) {
  Object.entries(this.props).forEach(([key, val]) =>
    prevProps[key] !== val && console.log(`Prop '${key}' changed`)
  );
  Object.entries(this.state).forEach(([key, val]) =>
    prevState[key] !== val && console.log(`State '${key}' changed`)
  );
}
 

Voici un petit crochet que j'utilise pour suivre les mises à jour des composants de la fonction

 function useTraceUpdate(props) {
  const prev = useRef(props);
  useEffect(() => {
    const changedProps = Object.entries(props).reduce((ps, [k, v]) => {
      if (prev.current[k] !== v) {
        ps[k] = [prev.current[k], v];
      }
      return ps;
    }, {});
    if (Object.keys(changedProps).length > 0) {
      console.log('Changed props:', changedProps);
    }
    prev.current = props;
  });
}
 

92voto

jpdelatorre Points 406

Voici quelques instances que Réagir composante sera de nouveau rendu.

  • Composant Parent rerender
  • Appelant this.setState() au sein de la composante. Cela va déclencher le composant suivant du cycle de vie des méthodes d' shouldComponentUpdate > componentWillUpdate > render > componentDidUpdate
  • Les changements dans la composante de l' props. Cela va déclencher componentWillReceiveProps > shouldComponentUpdate > componentWillUpdate > render > componentDidUpdate (connect méthode de react-redux déclencheur de cette quand il y a des changements dans le Redux magasin)
  • appelant this.forceUpdate qui est similaire à l' this.setState

Vous pouvez réduire votre composant rerender par la mise en œuvre d'une case à l'intérieur de votre shouldComponentUpdate et de revenir false si il n'est pas nécessaire.

Une autre façon est d'utiliser des React.PureComponent ou apatrides composants. Pure et apatrides uniquement les composants de re-rendre quand il y a des changements à ses accessoires.

12voto

Cumulo Nimbus Points 3404

@jpdelatorre la réponse est grande à mettre en évidence les raisons pourquoi Réagir composant de re-rendre.

Je voulais juste de plonger un peu plus profondément dans un cas: lorsque des accessoires de changer. Dépannage ce qui est à l'origine de Réagir composant à nouveau le rendu est un problème commun, et dans mon expérience, beaucoup de temps la traque de cette question consiste à déterminer quels accessoires sont en train de changer.

Réagir composants de rendre à nouveau chaque fois qu'ils reçoivent de nouveaux accessoires. Ils peuvent recevoir de nouveaux accessoires comme:

<MyComponent prop1={currentPosition} prop2={myVariable} />

ou si MyComponent est connecté à un redux du magasin:

function mapStateToProps (state) {
  return {
    prop3: state.data.get('savedName'),
    prop4: state.data.get('userCount')
  }
}

À tout moment la valeur de prop1, prop2, prop3ou prop4 change MyComponent re-rendu. Avec 4 accessoires, il n'est pas trop difficile de traquer les accessoires qui sont en train de changer en mettant un console.log(this.props) au début de l' render bloc. Cependant, avec plus compliqué de composants et de plus en plus des accessoires de cette méthode est intenable.

Ici est une approche utile (à l'aide de lodash pour des raisons de commodité) afin de déterminer les prop changements sont à l'origine d'un composant afin de rendre à nouveau:

componentWillReceiveProps (nextProps) {
  const changedProps = _.reduce(this.props, function (result, value, key) {
    return _.isEqual(value, nextProps[key])
      ? result
      : result.concat(key)
  }, [])
  console.log('changedProps: ', changedProps)
}

L'ajout de cet extrait de votre composant peut aider à révéler le coupable causant discutable re-rend, et de nombreuses fois, cela permet de faire la lumière sur les données inutiles adduction dans les composants.

3voto

pritesh Points 1304

Les réponses ci-dessus sont très utiles, juste au cas où si quelqu'un est à la recherche d'une méthode spécifique pour détecter la cause de rerender puis j'ai trouvé cette bibliothèque redux-enregistreur de très utile.

Ce que vous pouvez faire est d'ajouter la bibliothèque et de permettre la comparaison entre l'état(c'est là, dans les docs) comme:

const logger = createLogger({
    diff: true,
});

Et ajouter le middleware dans le magasin.

Ensuite, mettre un console.log() dans la fonction rendu du composant que vous souhaitez tester.

Ensuite, vous pouvez exécuter votre application et consulter les journaux de la console.Partout où il y a un journal juste avant, il va vous montrer la différence entre l'état (nextProps and this.props) et vous pouvez décider si le rendu est vraiment nécessaireenter image description here

Il sera semblable à l'image ci-dessus avec les diff clé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X