5
votes

Éviter le rendu dans React causé par des objets littéraux: comment faire avec les variables de l'objet?

J'ai lu dans cet article React est lent, React est rapide: optimisation des applications React en pratique que:

En fait, chaque fois que vous passez un objet littéral comme accessoire à un composant enfant, vous cassez la pureté.

D'accord, j'ai compris. Donc, le mieux pour éviter cela est de créer une variable avec l'objet, et d'insérer cette variable dans le prop, comme ça:

import React from 'react';

class App extends React.Component {

  style = () => ({
    marginTop: this.props.marginTop
  })

  render() {
    return(
      <div style={this.style()}>

      </div>
     )
  }
}

Mais que se passe-t-il si le prop de style dépend d'un reçu un accessoire? Où devrait être l'objet? Par exemple, j'ai ce composant:

import React from 'react';

const style = (marginTop) => ({ marginTop })
const AnyComponent = (props) => (
    <div style={style(props.marginTop)}>
        ...
    </div>
)

Est-ce une bonne pratique à faire:

import React from 'react';

const AnyComponent = (props) => (
    <div style={{ marginTop: props.marginTop }}>
        ...
    </div>
)

[EDIT] J'ai oublié de dire que la plupart de mes composants ont un état, alors dans ce cas, est-ce une bonne idée de faire:

import React from 'react';

const style = { marginTop: 10 };
const AnyComponent = (props) => (
    <div style={style}>
        ...
    </div>
)


2 commentaires

Vous compliquez trop les choses. Avez-vous un problème de performances?


En fait, je le fais: mon application est assez grande (beaucoup plus grande que cela), utilise redux, et l'un de mes composants imbriqués profonds utilise draft-js. Je voudrais stocker l'EditorState dans mon magasin Redux pour plus de commodité, mais je ne peux pas le faire maintenant à cause des performances et de trop nombreux problèmes de restitution rendant l'éditeur de texte à la traîne. Je voudrais donner une chance à cette optimisation, car j'en ai déjà fait beaucoup plus (recomposer, resélectionner, etc.)


3 Réponses :


2
votes

Vous pouvez créer votre variable dans votre composant, comme suit:

import React from 'react';

const AnyComponent = (props) => {
 // if props.marginTop is an object
 const style = props.marginTop;

 return (
    <div style={style}>
        ...
    </div>
)};


1 commentaires

Cela crée-t-il une nouvelle variable de style à chaque fois? L'objet style précédent et le style actuel auraient des adresses différentes, non?



2
votes

Auparavant, vous ne pouviez pas faire cela dans les composants fonctionnels (bien que vous puissiez utiliser la mémorisation) Mais maintenant, grâce aux hooks React, vous pouvez faire quelque chose comme ceci:

import React from 'react';

const style = (marginTop) => ({ marginTop })
const AnyComponent = (props) => (
    <div style={style(props.marginTop)}>
        ...
    </div>
)

Et non, vous ne pouvez pas utiliser celui-ci:

const AnyComponent = (props) => {
    const style = useMemo(() => ({ marginTop: props.marginTop }), [props.marginTop]);
    <div style={style}>
        ...
    </div>
}

Parce qu'il crée également un nouvel objet à chaque nouveau rendu d'AnyComponent en appelant la fonction de style à chaque fois.


2 commentaires

useMemo renvoie une valeur mémorisée, pas une fonction qui la renvoie. La suggestion avec getStyle serait vraie pour useCallback .


@estus Merci beaucoup pour votre commentaire. Je modifierai ma réponse



1
votes

Un objet peut être mémorisé avec le hook useMemo :

const AnyComponent = (({ marginTop }) => (
    const style = useMemo(() => ({ marginTop }), [marginTop]);
    <div style={style}>
        ...
    </div>
)

Puisque useMemo est destiné à des calculs coûteux et a sa propre surcharge, cela peut être considéré comme une optimisation prématurée pour le cas div .


4 commentaires

merci pour votre réponse, que proposez-vous pour les composants de classe? J'ai édité mon message avec une proposition, qu'en pensez-vous?


useMemo est spécifique aux composants fonctionnels. Vous pouvez utiliser un mémo à usage général comme Lodash. Comme je l'ai mentionné, cette optimisation n'a pas beaucoup de sens pour

. En ce qui concerne les composants de classe avec des accessoires personnalisés, il est préférable de les rendre responsables des décisions de rendu et d'utiliser shouldComponentUpdate.


@estus Pouvez-vous nous dire quels calculs coûteux sont nécessaires pour cela?


@EddieCooro Une fonction qui prend une quantité considérable de CPU ou de RAM, par exemple objet objet complexe.