Material-ui: Améliorer les performances de l'interface utilisateur matérielle

Créé le 23 mars 2018  ·  93Commentaires  ·  Source: mui-org/material-ui

Tout d'abord, merci beaucoup pour cette bibliothèque de composants géniale ! C'est bien!

J'ai ajouté un tiroir dans ma nouvelle application. La plupart du temps, j'ai copié-collé l'exemple de tiroir. Juste pour PoC j'ai multiplié

        <Divider />
        <List>{mailFolderListItems}</List>

section.

Après cela, cela semble très lent, en particulier sur un appareil mobile (nexus 4, cordova avec passage pour piétons 20). J'utilise le mode dev, mais le mode prod n'accélère pas beaucoup.

Grâce aux outils de développement de réaction, j'ai remarqué que les composants de mailFolderListItems s'affichaient à chaque clic sur un lien dans le routeur de réaction ou même dans le menu ouvert. Il faut parfois jusqu'à 50-60ms pour restituer UN {mailFolderListItems} . j'utilise

const modalProps = {
    keepMounted: true, // Better open performance on mobile.
};

Pour éliminer l'incertitude avec les autres composants de l'application, j'ai converti mailFolderListItems en composant et désactivé le rendu :

class MailFolderListItems extends React.Component<{}, {}> {

    shouldComponentUpdate() {
        return false;
    }

    render() {
        return (
            <List>
                <Link to={Routes.Startpage.path}>
                    <ListItem>
                        <ListItemIcon>
                            <InboxIcon />
                        </ListItemIcon>
[...]


                <Divider />
                <MailFolderListItems />

Après cela, cette partie se sent bien.

J'ai trouvé https://github.com/mui-org/material-ui/issues/5628 . Je suggère de le revoir . L'optimisation de shouldComponentUpdate est l'étape fondamentale et la plus importante pour gagner en performance. PureComponent n'est que le raccourci le plus courant.

De plus, j'ai remarqué que beaucoup de temps (1-2 ms et plus pour CHAQUE composant matériel-ui) est dépensé dans WithStyles .

  • [x] J'ai recherché les problèmes de ce référentiel et je pense qu'il ne s'agit pas d'un doublon.

Comportement prévisible

Je m'attends à obtenir la plupart des performances de réaction possibles pour cette excellente bibliothèque.

Comportement actuel

L'application devient plus lente avec chaque composant matériel-ui.

Étapes à reproduire (pour les bogues)

Je ne fournis pas encore d'exemple de reproduction, car je viens de copier-coller à partir de la page de démonstration du composant, mais si nécessaire, je peux fournir une démonstration de codesandbox. Pour le navigateur, cela est perceptible si le navigateur est ralenti d'un facteur >=5x dans les paramètres de performances.

Votre environnement

| Technologie | Versions |
|--------------|---------|
| Matériel-UI | 1.0.0-beta.38 |
| Icônes de matériel-UI | 1.0.0-beta.36 |
| Réagir | 16.2.0 |
| navigateur | passage pour piétons cordova 20 (égal à android chrome 50) |

discussion performance

Commentaire le plus utile

@oliviertassinari en tant que grand développeur, comment peux-tu écrire des choses comme ça ? Pourquoi utilisez-vous _vos hypothèses personnelles_ comme arguments et non comme faits ? Je pense que j'ai présenté suffisamment de faits ci-dessus. J'ai tout fait pour le montrer, car j'aime ce projet et j'ai envie d'y contribuer. Ce n'est pas assez? Ok, alors plus de faits et _pas_ d'hypothèses.

Rien que pour vous je réduis à 10 boutons. dix! Cela signifie que 10 composants (pire : des conteneurs) de material-ui ralentissent toute l'application jusqu'à ce que l'application ne soit

Bouton normal :
image

Bouton pur :
image

C'est encore une amélioration de 8x ! C'est énorme! Pouvez-vous imaginer à quel point cela est important sur un appareil mobile ?

Au lieu de 100 boutons, vous trouverez au maximum 10 boutons sur une page. Pourtant, vous trouverez 10 grilles, 10 X, etc.

J'ai utilisé Button car c'est l'un des composants les plus simples ! Cela montre que material-ui est cassé du point de vue des performances. Maintenant, imaginez un conteneur de composants comme une AppBar, une barre d'outils, une liste, un tiroir ! C'est encore pire ! Vous obtenez très rapidement 20 composants/conteneurs sur chaque page. Et parce que vous n'expirez aucune lenteur sur votre puissant ordinateur de bureau/mac, cela ne signifie pas que material-ui n'est pas incroyablement lent.

react-intl, la vérification entre les props précédente et nouvelle sera toujours fausse. Vous gaspillerez des cycles CPU. Donc x13 -> x0.8

Montrez-moi un exemple sur codesandbox. Je ne vois pas pourquoi cela devrait arriver. Je suis sûr que cela ne se produit que lors d'une mauvaise utilisation des composants de réaction. Et l'exemple officiel montre une mauvaise utilisation, car il semble que react-intl ne s'applique pas aux abonnés de contexte . Mais de nombreux autres composants sont alignés sur les directives de réaction et les meilleures pratiques pour rester performants.

BTW : WithStyles consomme jusqu'à 2,27 ms pour le bouton sur l'appareil mobile. 8 composants et vous sous 60fps.

Tous les 93 commentaires

Je m'attends à obtenir la plupart des performances de réaction possibles pour cette excellente bibliothèque.

@Bessonov Performance sera une mise au point après la version v1. Nous avons essayé de garder le noyau de la bibliothèque aussi vite que possible. Il devrait être suffisant pour +90% des cas. Du moins, c'est mon expérience d'utilisation de la bibliothèque jusqu'à présent. Vous n'avez fourni aucune référence externe, à part attirer notre attention sur le fait que la performance est importante, nous ne pouvons pas rendre ce problème exploitable. Si vous êtes en mesure d'identifier une limitation de la racine des performances de Material-UI que nous pouvons étudier (avec une reproduction de codesandbox ou de référentiel), veuillez l'augmenter. D'ici là, je clos le sujet.

@oliviertassinari merci pour ta réponse rapide ! Je suis très heureux d'apprendre que cette performance sera focalisée après la sortie.

Il devrait être suffisant pour +90% des cas. Du moins, c'est mon expérience d'utilisation de la bibliothèque jusqu'à présent.

Sur le bureau - oui, c'est le cas. Mais sur mobile, c'est vraiment lent. Just Drawer et quelques boutons rendent l'application lente. Il n'est pas réactif et consomme plus d'énergie au besoin.

Vous n'avez fourni aucune référence externe, à part attirer notre attention sur le fait que la performance est importante, nous ne pouvons pas rendre ce problème exploitable.

J'ai fourni une référence au problème déjà soulevé et une référence à la documentation de réaction.

Si vous êtes en mesure d'identifier une limitation de la racine des performances de Material-UI que nous pouvons étudier (avec une reproduction de codesandbox ou de référentiel)

Comme je l'ai dit, je peux le faire. Voici une comparaison des composants purs et non purs. Les étapes à reproduire sont :

  1. Utilisez Chrome et accédez à https://codesandbox.io/s/r1ov818nwm
  2. Cliquez sur "Ouvrir dans une nouvelle fenêtre" dans la fenêtre d'aperçu
  3. Ouvrez les outils de développement et accédez à l'onglet "performances"
  4. Réduisez votre CPU d'au moins 5x (selon votre PC - peut être 10x) pour refléter l'appareil mobile
  5. Cliquez sur burger et voyez comment il traîne.

Et maintenant:

  1. Aller à index.js
  2. changer pure en true
  3. sauvegarder
  4. Répétez les étapes ci-dessus
  5. Profitez-en!

Cet exemple est un peu irréaliste car j'ai inséré trop d'éléments de liste. Mais comme je l'ai dit, sur mobile, il arrive très rapidement au point où vous "ressentez" chaque action.

Voici mon problème avec WithStyles . C'est sur le bureau avec la limitation du processeur. Je voudrais publier des captures d'écran d'un appareil réel lundi.

Temps pour WithStyles(ListItem) :
image

Temps pour ListItem :
image

La différence est de 1,26 ms uniquement pour un composant ListItem . Avec 13 composants comme celui-ci, vous ne pouvez plus effectuer de rendu à 60 ips. Mais j'ai remarqué sur Desktop, que cette durée n'est pas toujours là.

Voici une comparaison des composants purs et non purs

Au fait, je ne dis pas que PureComponent est LA solution à tous les problèmes de performances. Je dis juste que cela peut être l'une des aides pour rendre material-ui utilisable sur mobile.

La différence est de 1,26 ms uniquement pour un composant ListItem.

@Bessonov Le composant WithStyles devrait être très bon marché pour les instances répétitives du même composant. Nous n'injectons le CSS qu'une seule fois.
Peut-être que vous atteignez les limites de React et le coût des composants d'ordre supérieur.
Il existe une gamme de solutions pour atténuer les problèmes de performances dans React. Par exemple, vous pouvez utiliser la mémorisation et la virtualisation d'éléments. Je garde ce problème ouvert comme point de départ pour une future enquête sur les performances.
Je ne pense pas qu'on puisse y faire grand chose pour le moment. Merci d'avoir soulevé le problème.

Ok, ce n'est qu'une partie. Que pensez-vous de la partie la plus importante - l'optimisation de shouldComponentUpdate ?

EDIT : Je veux diviser ce problème en deux parties. Cette partie est d'environ shouldComponentUpdate et l'autre partie pour WithStyles , si je peux montrer plus d'informations. C'est OK pour toi?

optimisation de shouldComponentUpdate

@Bessonov Nous volontairement une telle logique du côté Material-UI pour deux raisons :

  1. La plupart de nos composants acceptent les éléments de réaction, un changement de référence d'élément de réaction à chaque rendu, ce qui fait que la logique gaspille systématiquement des cycles CPU.
  2. Plus la logique shouldComponentUpdate est proche de la racine de l'arbre React, plus elle est efficace. Je veux dire, plus vous pouvez faire de taille sur l'arbre, mieux c'est. Les composants Material-UI sont de bas niveau. Il y a une faible opportunité de

La seule opportunité que nous ayons trouvée concerne les icônes. Faites-nous savoir si vous pouvez en identifier de nouveaux.

l'autre partie pour WithStyles

+90% du temps passé dans WithStyles est en fait passé dans JSS , il y a très peu de choses que nous pouvons faire à ce sujet du côté Material-UI.
Au moins, j'ai récemment identifié une opportunité de mise en cache pour le rendu côté serveur afin d'améliorer considérablement les performances sur le rendu répétitif. Mais c'est côté serveur uniquement.

La plupart de nos composants acceptent des éléments de réaction, un changement de référence d'élément de réaction à chaque rendu, ce qui fait que la logique gaspille systématiquement des cycles CPU.

Cela dépend de l'utilisation et peut être amélioré. Je ne me compare pas, mais je suis sûr qu'une bonne utilisation des composants et un shouldComponentUpdate optimisé (avec une comparaison superficielle) sont moins coûteux que des composants non optimisés, en particulier pour les structures immuables (et immutable.js n'est pas requis d'ailleurs). Billet associé : https://github.com/mui-org/material-ui/issues/4305

Par exemple dans https://github.com/mui-org/material-ui/blob/v1-beta/docs/src/pages/demos/drawers/PermanentDrawer.js#L68 cela conduit à de nouveaux objets et fait PureComponent insensé :

        classes={{
          paper: classes.drawerPaper,
        }}

car il renvoie à chaque fois un nouvel objet. Mais non:

const drawerClasses = {
    paper: classes.drawerPaper,
};
[...]
        classes={drawerClasses}

Idem pour les composants.

Plus la logique shouldComponentUpdate est proche de la racine de l'arborescence React, plus elle est efficace. Je veux dire, plus vous pouvez faire de taille sur l'arbre, mieux c'est.

Oui c'est vrai.

Les composants Material-UI sont de bas niveau. Il y a une faible opportunité de levier.

C'est en partie vrai. Comme vous pouvez le voir sur https://codesandbox.io/s/r1ov818nwm, je viens d'envelopper List dans PureComponent . Rien d'autre et cela accélère le tiroir par un facteur important. Je dirais que cela est vrai pour chaque composant, du moins qui utilise {this.props.children} . J'ai créé une autre démo : https://codesandbox.io/s/my7rmo2m4y

Il n'y a que 101 Buttons (pure = false) et Buttons encapsulés dans PureComponent (pure = true, voir d'où le Button est importé). Même résultat de jeu, si je clique sur le bouton « Clic » :

Bouton normal :
image

Bouton enveloppé (avec frais généraux et ainsi de suite) :
image

Comme vous pouvez le voir, il y a 637 ms contre 47 ms pour les boutons normaux ! Pensez-vous toujours qu'optimiser shouldComponentUpdate (ou juste PureComponent ) ne vaut pas la peine ? :)

EDIT : correction du libellé au début

@oliviertassinari @oreqizer J'ai remarqué une chose intéressante. Il semble que l'extension PureComponent fonctionne mieux que Component avec

  shouldComponentUpdate() {
    return false;
  }

image

EDIT: Je pense que c'est l'une des optimisations internes réactives.

Comme vous pouvez le voir, il y a 637 ms contre 47 ms pour les boutons normaux ! Pensez-vous toujours que l'optimisation de shouldComponentUpdate (ou simplement PureComponent) ne vaut pas la peine ? :)

@Bessonov C'est démontrer le potentiel de la logique pure. Oui, ça peut être très utile ! C'est une amélioration x13. Mais je ne pense pas que ce soit proche des conditions réelles :

  • Au lieu de 100 boutons, vous trouverez au maximum 10 boutons sur une page. Pourtant, vous trouverez 10 grilles, 10 X, etc.
  • Au lieu de simples propriétés fournies aux éléments de niveau inférieur, vous utiliserez quelque chose comme react-intl, la vérification entre les props précédents et nouveaux sera toujours fausse. Vous gaspillerez des cycles CPU . Donc x13 -> x0.8 ou plus

@oliviertassinari en tant que grand développeur, comment peux-tu écrire des choses comme ça ? Pourquoi utilisez-vous _vos hypothèses personnelles_ comme arguments et non comme faits ? Je pense que j'ai présenté suffisamment de faits ci-dessus. J'ai tout fait pour le montrer, car j'aime ce projet et j'ai envie d'y contribuer. Ce n'est pas assez? Ok, alors plus de faits et _pas_ d'hypothèses.

Rien que pour vous je réduis à 10 boutons. dix! Cela signifie que 10 composants (pire : des conteneurs) de material-ui ralentissent toute l'application jusqu'à ce que l'application ne soit

Bouton normal :
image

Bouton pur :
image

C'est encore une amélioration de 8x ! C'est énorme! Pouvez-vous imaginer à quel point cela est important sur un appareil mobile ?

Au lieu de 100 boutons, vous trouverez au maximum 10 boutons sur une page. Pourtant, vous trouverez 10 grilles, 10 X, etc.

J'ai utilisé Button car c'est l'un des composants les plus simples ! Cela montre que material-ui est cassé du point de vue des performances. Maintenant, imaginez un conteneur de composants comme une AppBar, une barre d'outils, une liste, un tiroir ! C'est encore pire ! Vous obtenez très rapidement 20 composants/conteneurs sur chaque page. Et parce que vous n'expirez aucune lenteur sur votre puissant ordinateur de bureau/mac, cela ne signifie pas que material-ui n'est pas incroyablement lent.

react-intl, la vérification entre les props précédente et nouvelle sera toujours fausse. Vous gaspillerez des cycles CPU. Donc x13 -> x0.8

Montrez-moi un exemple sur codesandbox. Je ne vois pas pourquoi cela devrait arriver. Je suis sûr que cela ne se produit que lors d'une mauvaise utilisation des composants de réaction. Et l'exemple officiel montre une mauvaise utilisation, car il semble que react-intl ne s'applique pas aux abonnés de contexte . Mais de nombreux autres composants sont alignés sur les directives de réaction et les meilleures pratiques pour rester performants.

BTW : WithStyles consomme jusqu'à 2,27 ms pour le bouton sur l'appareil mobile. 8 composants et vous sous 60fps.

Pourquoi utilisez-vous vos hypothèses personnelles comme arguments et non comme faits ?

Qu'est-ce qui vous fait penser que c'est une supposition personnelle? J'essayais de faire preuve d'esprit critique. D'un point de vue conceptuel, la traversée d'accessoires supplémentaire ralentira la version pure par rapport à la version non pure, elle doit élaguer quelque chose qui en vaut la peine. Même raisonnement que #5628 ou https://github.com/react-bootstrap/react-bootstrap/issues/633#issuecomment -234749417 ou https://github.com/reactstrap/reactstrap/pull/771#issuecomment -375765577

Avec pur :
capture d ecran 2018-03-27 a 11 43 41

Sans pur :
capture d ecran 2018-03-27 a 11 44 15

La reproduction est la suivante.

@oliviertassinari es-tu sûr que codesandbox fait tout pour ton test ? Parce que mes résultats sont très différents :

Sans pur (même sans accélérateur c'est lent) :
image

Pure (après avoir changé pour true et enregistré, j'obtiens une nouvelle URL pour codesandbox):
image

Comme il ne vérifie pas les changements de contexte et oblige également les utilisateurs à s'assurer que tous les composants enfants sont également "purs", je ne pense pas que cela convienne à cette bibliothèque. Cette bibliothèque doit être aussi flexible que possible et je pense que cela la rendra plus difficile à utiliser.

Je vois le point. Mais c'est un compromis très intéressant. D'un côté, même material-ui devrait être "aussi flexible que possible", mais de l'autre côté, les performances actuelles le rendent _inutilisable_ du tout.

Peut-être devriez-vous penser à fournir une version pure et non pure des composants. Je le fais maintenant pour que mon application obtienne des performances utilisables même sur le bureau.

@Bessonov La codesandbox n'a pas été enregistrée correctement. Désolé. Il manquait le diff suivant. J'ai mis à jour le lien :

<Button>
+ <i>
    Button
+ </i>
</Button>

Je ne comprends pas pourquoi cela devrait produire des résultats différents? J'obtiens un meilleur graphique, mais la version non pure est nettement plus lente.

EDIT : ok, je vois. Essayez de comprendre ce qui se passe...

OK je comprends maintenant. Juste le même "nouvel objet à chaque rendu". Je ne l'avais pas remarqué avant. Dans certains cas, il peut être amélioré avec des constantes via le plugin babel automatiquement.

Eh bien, vous le savez déjà ! :D Même s'il n'y a pas beaucoup d'avantages en soi (vous avez montré ~7%), c'est toujours rentable en conclusion avec des composants purs pour éviter certains défauts que vous mentionnez ci-dessus. Je l'ai testé maintenant avec Pure Wrapper + plugin babel + build de production et c'est impressionnant de rapidité sur le même appareil mobile !

Comme je l'ai dit, je pense qu'il est préférable d'offrir les deux - des composants non purs pour la flexibilité et des composants purs (les enveloppes suffisent pour que cela reste simple et maintenable) pour les performances. Mais pour moi, je peux vivre avec uniquement des composants purs, car l'amélioration globale des performances est bien supérieure aux inconvénients des performances. Ou mieux : je ne peux pas utiliser material-ui sans composants purs.

Ok, pour l'instant, j'attends d'autres commentaires sur ce sujet et je crée mes propres wrappers dans mon application)

Merci pour les idées !

Je n'ai jamais entendu parler de transform-react-constant-elements réellement utilisés et vraiment utiles. C'est bien comme une micro-optimisation aléatoire à lancer, mais en pratique, vous écrivez rarement du code assez simple pour en tirer beaucoup. Cependant, je suppose que ce ne serait pas une mauvaise optimisation pour tous les composants d'icônes de style SVG comme <Add /> .

Jetez un œil à cet exemple (cliquez sur Plugins sur le côté, recherchez "react-constant" et cochez la case "transform-react-constant-elements") et vous verrez que presque rien n'a été optimisé :

  • Le simple InputAdornment statique a été déplacé vers le haut, oui.
  • Mais le bouton d'envoi trivialement simple n'était plus optimisé au moment où nous y mettions un gestionnaire d'événements.
  • Et tandis que l'InputAdornment lui-même est maintenant hissé, le InputProps={{startAdornment: ...}} est toujours en ligne et crée un nouvel objet à chaque rendu, ce qui rend PureComponent impossible.
  • De même, classes={{label: classes.runButtonLabel}} empêche PureComponent d'optimiser le bouton Exécuter.

Personnellement, j'aime PureComponent et j'essaie de l'utiliser absolument partout et d'optimiser les choses autant que possible pour que cela fonctionne. Mais il ne semble pas du tout que MUI soit conçu de manière à ce que PureComponent fonctionne.

  • Les accessoires *Props comme InputProps sont un modèle fondamental du fonctionnement de MUI. Ce n'est pas seulement un moyen avancé de modifier les composants internes de l'interface MUI lorsque vous en avez besoin, mais plutôt quelque chose qui est utilisé régulièrement dans des cas d'utilisation simples. Ce modèle rend souvent non optimisable tout composant feuille qui pourrait normalement être optimisé en mode pur.
  • De même, le modèle classes={{...}} ne fonctionne pas non plus avec PureComponent et c'est le moyen d'ajouter n'importe quel style aux choses dans MUI. (Et dire d'utiliser classes={classes} n'est en aucun cas pratique car un consommateur réel a probablement un nom de classe différent de celui de la classe interne du composant et classes est susceptible d'inclure également des classes destinées à styliser d'autres éléments dans le même composant consommateur)
  • Les enfants sont beaucoup utilisés, au lieu d'avoir 1 composant, un modèle commun utilise souvent 2-3 et un seul d'entre eux peut être optimisé pur si l'un d'entre eux le peut.

Si nous voulons optimiser quoi que ce soit, ces problèmes fondamentaux doivent être résolus, sinon le simple fait de laisser les gens activer une MUI en mode pur n'optimisera pas grand-chose du tout. Je peux penser à deux possibilités.

Nous autorisons simplement l'activation du mode pur, les consommateurs doivent mémoriser ou hisser des objets manuellement pour obtenir réellement des optimisations

  1. Une façon à laquelle je peux penser pour le faire serait un peu de shallowMemoize qui utilise le this local et un key (vous pouvez donc l'utiliser sur différents bits de données) qui mémorise les données tant qu'elles sont superficielles égales
  2. Un autre auquel je peux penser est d'utiliser quelque chose comme resélectionner pour créer des sélecteurs qui mémoriseront les données.
  3. Une autre façon de faire le shallowMemoize en 1. serait de le passer à render() avec un décorateur. De cette façon, nous pourrions en transmettre un nouveau à chaque rendu et au lieu d'avoir besoin de key nous pouvons simplement vérifier si l'un des objets mémorisés du dernier rendu doit être réutilisé, puis rejeter toutes les anciennes valeurs.

Le problème, bien sûr, est que cela rend les consommateurs beaucoup plus gros et désordonnés et nécessite que la logique soit manuellement hissée à des endroits où elle est éloignée du code qui l'utilise.

import {createSelector} from 'reselect';

class FormPage extends PureComponent {
  state = { example: '' };

  change = e => this.setState({example: e.target.value});
  submit = () => {
    console.log('Submit: ', this.state.example);
  };

  runButtonClasses = createSelector(
    props => props.classes.runButtonLabel,
    runButtonLabel => ({runButtonLabel}));

  render() {
    const {title} = this.props;
    const {example} = this.state;

    return (
      <form>
        {title}
        <TextField
          InputProps={this.shallowMemoize('a', {
            // This example assumes use of transform-react-constant-elements to make this object always the same
            startAdornment: <InputAdornment position="start">Kg</InputAdornment>,
          }}}
          onChange={example}
          value={example} />
        <Button classes={this.runButtonClasses(classes)}>Run</Button>
        <Button onClick={this.submit}>Submit</Button>
      </form>
    );
  }
}
// ...
  <strong i="6">@withShallowMemoize</strong>
  render(memo) {
    const {title} = this.props;
    const {example} = this.state;

    return (
      <form>
        {title}
        <TextField
          InputProps={memo({
            startAdornment: <InputAdornment position="start">Kg</InputAdornment>,
          }}}
          onChange={example}
          value={example} />
        <Button classes={memo(classes)}>Run</Button>
        <Button onClick={this.submit}>Submit</Button>
      </form>
    );
  }

Au lieu d'essayer d'optimiser les InputProps, les classes, etc... nous encourageons les gens à créer des micro-composants pour toutes leurs casses d'utilisation

Si c'est la manière recommandée d'utiliser MUI, nous n'aurons peut-être même pas besoin d'un mode pur. Comme vous pouvez le voir, dès que vous commencez à créer de petits composants d'aide pour vos cas d'utilisation courants, ces composants eux-mêmes peuvent facilement être des composants purs. Dans l'exemple, WeightTextField n'est désormais plus rendu à nouveau tant que value est toujours le même, sautant complètement avec Styles, tout travail de mémorisation nécessaire pour InputProps ou la configuration InputAdornment. Et quand value change, nous devons de toute façon re-rendre TextField afin que le InputProps={{...}} non pur n'ait pas d'importance.

Je suis bien avec ce chemin. J'aime les micro-composants en théorie ; bien que je déteste toutes les syntaxes/modèles actuellement valides pour les écrire auxquels je peux penser. Je ne veux pas MyComponent = enhance(MyComponent) , je veux les décorer, mais vous ne pouvez décorer aucune des manières courtes d'écrire un petit composant. Je n'aime pas non plus transformer import {TextField} from 'material-ui'; en import WeightTextField from '../../../ui/WeightTextField ;`.

```js
let WeightTextField = ({unit, InputProps, ...props}) => (
{... accessoires}
InputProps={{
startParure :{unité} ,
...InputProps
}}
onChange={exemple}
valeur={exemple} />
);
WeightTextField = pure(WeightTextField);

RunButton = composer(
withStyles(thème => ({
étiqueter: {
fontWeight: '800',
},
})),
pur
)(Bouton);

const SubmitButton = pure(Button);

la classe FormPage étend le composant {
état = { exemple : '' } ;

change = e => this.setState({exemple : e.target.value});
soumettre = () => {
console.log('Envoyer : ', this.state.example);
} ;

rendu() {
const {titre} = this.props;
const {exemple} = this.state;

return (
  <form>
    {title}
    <WeightTextField
      unit='Kg'
      onChange={example}
      value={example} />
    <RunButton>Run</RunButton>
    <SubmitButton onClick={this.submit}>Submit</SubmitButton>
  </form>
);

}
}
````

J'ai un cas d'utilisation où j'ai besoin d'afficher 500 à 2 000 cases à cocher sur une page dans une grande liste. En utilisant les cases à cocher du navigateur natif, les performances sont bonnes, mais en utilisant le composant <Checkbox> , les performances sont très médiocres et évoluent de manière linéaire avec le nombre de cases à cocher sur la page. Exemple : https://codesandbox.io/s/5x596w5lwn

J'utilise mui@next - existe-t-il une stratégie que je peux utiliser _maintenant_ pour rendre cela réalisable ?

@wilsonjackson
Tout d'abord, ne faites pas ce qui suit. Cela créera un nouveau gestionnaire à chaque case à cocher à chaque rendu, ce qui désoptimisera toutes les optimisations PureComponent que vous essayez de faire.

  handleChange = index => event => {
    this.setState({

Deuxièmement, créez votre propre petit composant pour envelopper Checkbox et rendre ce composant pur. Cela présente l'avantage supplémentaire que vous pouvez ajouter dans toutes les propriétés communes à toutes vos cases à cocher. Et, puisque vous avez le problème commun d'avoir besoin d'un gestionnaire d'événements de changement différent pour chaque élément, nous pouvons utiliser un composant de classe et le faire dans le composant plutôt que dans le conteneur de liste.

https://codesandbox.io/s/r7l64j6v5n

Si nous voulons optimiser quoi que ce soit, ces problèmes fondamentaux doivent être résolus, sinon le simple fait de laisser les gens activer une MUI en mode pur n'optimisera pas grand-chose du tout. Je peux penser à deux possibilités.

@dantman Ces choix d'API ont été faits dans le but d'améliorer au maximum le DX tout en essayant d'être assez rapide.

Au lieu d'essayer d'optimiser les InputProps, les classes, etc... nous encourageons les gens à créer des micro-composants pour toutes leurs casses d'utilisation

Oui. Le modèle d'emballage est certainement la manière encouragée de personnaliser la bibliothèque. Il peut être étendu pour appliquer des optimisations de performances. C'est plus facile sur l'espace utilisateur où la variabilité de l'utilisation des composants est beaucoup plus faible. Nous pourrions même ajouter une question FAQ ou une section guide sur ce point dans la documentation.

Oui. Le modèle d'emballage est certainement la manière encouragée de personnaliser la bibliothèque. Il peut être étendu pour appliquer des optimisations de performances. C'est plus facile sur l'espace utilisateur où la variabilité de l'utilisation des composants est beaucoup plus faible. Nous pourrions même ajouter une question FAQ ou une section guide sur ce point dans la documentation.

D'accord. Dans ce cas:

  • Nous voudrons recommander des bibliothèques comme recompose qui facilitent l'écriture de petits composants sans état. Zut, je serais heureux si quelqu'un me disait qu'il existe un autre modèle ou une bibliothèque similaire à recomposer mais qui permet de créer des fonctions pures sans état comme les modèles de recompose mais qui est aussi agréable que d'utiliser la syntaxe du décorateur
  • Comme nous énumérons des suggestions sur la façon d'utiliser les différentes bibliothèques de saisie semi-automatique et css dans les bibliothèques js avec MUI, nous voudrons probablement également suggérer les différents modèles d'organisation des dossiers existants et les bibliothèques de piratage de chemin (celles qui vous permettent de transformer les importations de ../../../../ui/Foo dans quelque chose comme something-local/Foo ) qui peut être utilisé pour rendre l'utilisation de votre propre série locale de micro-composants enveloppant MUI aussi agréable que l'utilisation de import {TextField} from 'material-ui'; et ne pas se sentir comme une régression dans la facilité du développeur .

@dantman fantastique, merci.

J'ai eu plusieurs fois besoin d'appliquer sCU car withStyles (ou plutôt JSS) était très lent. Je ne connais pas le code de JSS mais j'ai l'impression qu'il pourrait être beaucoup optimisé. J'utilise généralement des composants stylisés ou glamour et je me retrouve donc avec JSS et l'un des autres dans l'application et les deux surpassent JSS.

Bien que ces cas puissent être un peu ennuyeux, ils sont faciles à contourner avec le sCU au niveau de l'application ou des mises à jour d'état plus intelligentes. Je n'ai pas encore vu un seul composant MUI être suffisamment lent pour être problématique et je n'ai pas encore codé réellement à l'intérieur de MUI pour prendre beaucoup de temps.

Cela ne veut pas dire que cela ne pourrait pas être plus rapide et sûr que ce serait plus agréable si moins de surveillance était nécessaire, mais au moins à ce que je vois, il vaudrait mieux passer du temps à optimiser JSS directement que MUI dans ce cas.

@Pajn Merci pour les commentaires. Ce serait vraiment génial de voir une situation où les performances de withStyles sont problématiques ou où elles sont surpassées par les composants stylisés.

quelqu'un a-t-il vérifié ce référentiel https://github.com/reactopt/reactopt ?

$ click - button (text: مقالات ) => CssBaseline,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,ScrollbarSize,TransitionGroup,TouchRipple,Ripple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,Main,ScrollbarSize,TransitionGroup,TouchRipple,Ripple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple

ces composants effectuent un nouveau rendu inutile juste pour un simple clic, pourquoi ne pas essayer le cycle de vie de la mise à jour des composants ?

@nimaa77

quelqu'un a-t-il vérifié ce référentiel https://github.com/reactopt/reactopt ?
Non, j'utilise les fonctionnalités des outils de développement simples Why-did-you-update et chrome/react.

ces composants effectuent un nouveau rendu inutile juste pour un simple clic, pourquoi ne pas essayer le cycle de vie de la mise à jour des composants ?

Voir la discussion ci-dessus. Cela ne convient pas à tous les cas d'utilisation. Pour moi, il semble que material-ui devrait offrir à la fois des versions pures et non pures des composants. Je vois une énorme amélioration des performances avec des composants purs.

@dantman

Jetez un œil à cet exemple (cliquez sur Plugins sur le côté, recherchez "react-constant" et cochez la case "transform-react-constant-elements") et vous verrez que presque rien n'a été optimisé :

Ce n'est qu'une façon de résoudre ce problème. Il existe également d'autres options, plugins et autres optimisations artisanales. Ne vous méprenez pas, mais je ne suis pas intéressé par les discussions théoriques sur les optimisations bonnes ou mauvaises. Je suis intéressé par l'optimisation pratique qui fonctionne. Du moins dans ma configuration. Tout ce que j'ai écrit ci-dessus FONCTIONNE pour moi et rend mon application au moins utilisable sur les appareils mobiles bas-moyens. Bien que je sois obligé de faire plus d'optimisations comme la réorganisation des arborescences de composants, les performances atteintes ne seraient pas possibles sans des composants purs et d'autres optimisations automatiques. Et oui, je profile et optimise beaucoup pour y parvenir.

@Bessonov peut-être que nous pouvons utiliser un accessoire pour que la méthode shouldComponentUpdate fasse une comparaison superficielle (https://reactjs.org/docs/shallow-compare.html) OU retourne toujours false,
cela n'augmentera pas la taille du bundle avec deux versions de composants (pur et normal)

@lucasljj Je ne m'attends pas à une augmentation significative de la taille du paquet si cela est fait comme un wrapper pour un composant avec état comme mentionné ci-dessus. Voir aussi les profils ci-dessus : seuls les composants purs sont plus rapides que return false; dans sCU.

Le problème avec les composants purs ou les composants implémentant sCU est si vous utilisez un composant non pur à l'intérieur ou children . Voir les déclarations ci-dessus. Un autre problème à résoudre est le changement de thème. Non testé, mais je pense que cela peut être surmonté au moins avec l'API Context.

@bossonov Pure Components est considéré comme la réaction par défaut qui aurait dû être, qui ne le sont pas parce qu'ils sont arrivés en retard à la fête. Mais je suis d'accord que la plupart des gens vont créer des wrappers de style de formulaire redux en atténuant l'absence de celui-ci sur le sous-arbre

le problème auquel vous faites référence concernant les composants purs et les enfants ne se produit que si les accessoires de niveau supérieur ne se propagent pas aux enfants. Chaque prop ou changement d'état déclenchera un rendu à travers l'arborescence enfant jusqu'au niveau où le prop ne se propage pas.
Parce que l'idée des composants purs est qu'il se restitue à chaque changement d'accessoire ou d'état. Je ne connais pas intimement les éléments internes, mais je me demandais In vous ne pouviez pas utiliser une propriété de changement par composant que vous transmettez à chaque enfant. Vous pouvez même utiliser la nouvelle API de contexte à cette fin afin de ne pas avoir à transmettre un accessoire à travers l'arbre entier.

@oliviertassinari

Les performances seront un focus après la version v1.

Super, la v1 est sortie :) Y a-t-il une idée du moment où les performances doivent être abordées ? J'ai remarqué que ce problème ne fait pas partie du jalon post v1.

@Bessonov Je pense que ce serait bien de passer du temps à mettre à jour la FEUILLE DE ROUTE. Concernant les performances. J'ai deux choses en tête d'action, mais j'espère en découvrir plus :

  1. Nous ne pouvons pas améliorer quelque chose que nous ne pouvons pas voir. Nous avons besoin d'une référence. J'ai vu deux bibliothèques intéressantes jusqu'à présent:
  2. Le rendu côté serveur CSS nécessite environ 30% de ce que React doit rendre. Parce que nous ne supportons pas style = f(props) (enfin, nous ne le supportons pas encore : #7633). Nous pouvons implémenter une capacité de mise en cache très efficace, réduisant le coût de près de 0% pour les demandes répétées. Je pourrais travailler là-dessus pour le bureau si la performance SSR nuit à nos mesures commerciales.
    Mais ce ne sont pas les seules options, nous pouvons également penser aux plugins Babel pour appliquer les préréglages JSS coûteux au moment de la compilation plutôt qu'au moment de l'exécution (pour équilibrer les implications de la taille du paquet) cc @kof.

Merci pour les URL.

Entièrement d'accord avec 1 et lié #4305 ci-dessus.

  1. SSR peut aider avec le chargement de la première page, mais n'aide pas avec le rendu lent ou le cordova. Bien que personnellement, je puisse ignorer le premier chargement sur un ordinateur de bureau ou même sur un mobile, le rendu lent affecte toujours les appareils mobiles après le premier chargement.

Les optimisations du temps de compilation seraient excellentes et, de mon point de vue, devraient être préférées, car elles peuvent améliorer le premier chargement et le nouveau rendu.

Une autre chose est une sorte de documentation ou d'exemple de projet sur la façon d'utiliser mui (et babel, etc.) pour obtenir de meilleures performances.

Je ne sais pas si jss-cache peut être utilisé.

Le pipeline de prétraitement ISTF + sera capable de raser quelques ms.

Le samedi 19 mai 2018, 19:06 Anton Bessonov [email protected] a écrit :

Merci pour les URL.

Entièrement d'accord avec 1 et lié #4305
https://github.com/mui-org/material-ui/issues/4305 ci-dessus.

  1. SSR peut aider avec le chargement de la première page, mais n'aide pas avec le lent
    rendu ou cordova. Bien que personnellement, je puisse ignorer le premier chargement sur
    ordinateur de bureau ou même mobile, le rendu lent affecte toujours les appareils mobiles après
    premier chargement.

Les optimisations du temps de compilation seraient formidables et, de mon point de vue, devraient
être préféré, car il peut améliorer le premier chargement et le nouveau rendu.

Une autre chose est une sorte de documentation ou d'exemple de projet comment utiliser mui
(et babel etc.) pour obtenir de meilleures performances.

Je ne sais pas si jss-cache http://cssinjs.org/jss-cache?v=v3.0.0 peut être
utilisé.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/mui-org/material-ui/issues/10778#issuecomment-390418709 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AADOWGrCxNGqrT4MijiX8r9Ad32z6RsJks5t0FEtgaJpZM4S4woq
.

Peut être utile pour configurer des repères :
https://github.com/A-gambit/CSS-IN-JS-Benchmarks/blob/master/RESULT.md

Oh react-jss (qui est utilisé par material-ui) semble être assez lent

@janhoeck ce n'est pas le cas, et vous ne pourrez pas prouver le contraire, j'en suis sûr.

@kof Je comprends bien que les micro-benchmarks ne disent pas grand-chose, mais 4x-6x par rapport à aphrodite est vraiment lent. En fait, les performances globales de material-ui ne sont pas brillantes.

4x-6x par rapport à aphrodite est vraiment lent

@Bessonov La méthodologie de benchmark
https://twitter.com/necolas/status/954024318308007937?lang=fr

Les résultats dans mon navigateur :
⚠️ avec l'incertitude

capture d ecran 2018-06-12 a 17 58 54

la performance globale du matériel-ui n'est pas brillante

Nous pourrions très bien être limités par React lui-même et le coût des composants.

@Bessonov quoi que vous ayez utilisé pour vérifier les performances, quand il s'agit d'aphrodite, ce n'est pas vrai, car il utilise dès que possible et retarde le rendu, donc la plupart des benchmarks mesurent le temps cpu mais pas les performances de rendu final. Ceci étant dit le banc posté par @oliviertassinari est des plus réalistes.

En ce qui concerne les performances MUI, vous pouvez être plus rapide lorsque vous n'utilisez aucune abstraction, mais ce n'est pas le but. MUI suivant est assez rapide. Il est si rapide que vous ne devriez jamais vous soucier de ses performances, à moins que VOUS n'ayez fait quelque chose de complètement faux ou que vous n'ayez pas utilisé la bibliothèque.

@kof non, MUI n'est pas rapide par défaut. Nous sommes obligés de mettre en œuvre des solutions de contournement pour obtenir des performances acceptables. Bien sûr : n'avez-vous pas vu qu'il s'agit d'appareils mobiles et non de macs haut de gamme ?

ne vous inquiétez jamais de ses performances à moins que VOUS n'ayez fait quelque chose d'entièrement mal ou mal utilisé la bibliothèque

Eh bien, ci-dessus se trouvent quelques exemples de codesanbox. Si nous utilisons simplement des composants MUI dans un conteneur et enregistrons les valeurs d'entrée dans l'état du conteneur, comme cela a été montré dans les démonstrations de composants, cela devient très rapidement inutilisable. Enveloppez PureComponent, utilisez des composants non contrôlés, réorganisez l'arborescence, éléments constants, mémorisez, etc., nous aidant à maintenir des performances acceptables. Vous êtes invités à montrer comment utiliser MUI correctement, pour obtenir de meilleurs résultats, par exemple dans (atm, nous n'utilisons plus de tiroir):
https://codesandbox.io/s/r1ov818nwm

@oliviertassinari merci pour le lien. Voici les résultats pour Chrome 66 sur Nexus 4. Comme vous pouvez le voir, les résultats sont 10 fois moins bons. Je pense que dans le passage pour piétons 21/chrome 51, cela peut être un peu plus lent :

screenshot_2018-06-12-18-20-19

Nous pourrions très bien être limités par React lui-même et le coût des composants.

IMHO pas nécessairement, comme mentionné par d'autres aussi. Chaque rediffusion évitée est une grande victoire pour les performances et la batterie. N'oubliez pas, la performance est le troisième point de votre feuille de route :+1:

Voyez-le de cette façon : si ce que vous faites avec cssinjs est trop lent sur un appareil mobile, vous ne devriez pas non plus l'utiliser pour cette réaction et la plupart des autres choses. Si cssinjs vous ralentit, le composant React vous ralentit beaucoup plus. Vous devez repenser l'abstraction de niveau ob ou appliquer des optimisations.

@oliviertassinari c'est ça evtl. possible que mui wrapper rende les styles jss lors de la mise à jour? Il pourrait y avoir une fuite potentiellement qui fait un travail inutile.

@kof

Voyez-le ainsi [...]

Je vois ce que tu veux dire. Mais les composants réactifs et réactifs (purs) ne sont pas en eux-mêmes des goulots d'étranglement et fonctionnent très bien. Par exemple, MUI n'utilise pas PureComponent (avec les avantages et les inconvénients décrits ci-dessus), mais ils nous protègent la vie. @oliviertassinari a mentionné qu'il y a une chance d'obtenir de meilleures performances en utilisant des caches ou un pré-compilateur.

Ne vous méprenez pas, vous êtes des gars géniaux et je suis vraiment heureux de chaque version de MUI :clap: Mais vous devez également tenir compte des performances, car tous les utilisateurs ne visitent pas des sites Web via un ordinateur de bureau hautes performances .

si réagir n'est pas un goulot d'étranglement des performances et que vous en êtes sûr, JSS ne le sera pas non plus. La seule chose que je puisse imaginer qui doit être validée s'il y a du travail inutile en cours et que css est régénéré lors de la mise à jour.

Le composant pur est quelque chose que VOUS devriez utiliser dans votre code au niveau de l'application, si vous avez besoin d'une optimisation. MUI n'a pas à le faire, c'est une bibliothèque générique et ne doit faire aucune hypothèse. PureComponent n'est pas toujours bon.

JSS a pris en compte les performances dès le premier jour et j'ai passé des heures interminables en micro-optimisations.

C'est ridicule. Je ne peux pas empêcher le rendu des composants matériels de l'interface utilisateur à chaque interaction. Peu importe ce que je fais, même quelque chose d'aussi simple que ceci :

class RowText extends Component {
  shouldComponentUpdate = (nextProps, nextState) => {
    return false;
  };

  render() {
    const { title, artist } = this.props;
    return <ListItemText primary={title} secondary={artist} />;
  }
}

Déclenche le rendu des éléments de typographie sous-jacents. Comment est-ce possible ?

Hé, cela ne se produit qu'avec la liste et l'élément de liste. Pourquoi ? Y a-t-il quelque chose que je peux faire ?

@ danielo515 Difficile à dire sans l'exemple complet. Les composants List utilisent également le contexte, donc si vous modifiez également cette valeur, cela déclenchera également des rendus.

Je comprends que @eps1lon. Cependant, pourriez-vous s'il vous plaît expliquer comment un changement de contexte peut se produire? Je ne passe rien au composant de liste, je rends juste une perte d'enfants à l'intérieur.

@danielo515 Fondamentalement, à chaque fois que le List restitué. La nouvelle API de contexte a permis certaines stratégies d'optimisation que nous pouvions explorer en mémorisant la valeur du contexte.

L'API de contexte réagit actuellement déclenche un rendu sur chaque consommateur si la valeur change WRT en égalité stricte. Puisque nous créons un nouvel objet dans chaque appel de rendu à List chaque consommateur sera également restitué.

Donc, pour l'instant, un boost de perf simple serait d'envelopper le List afin qu'il ne se restitue pas aussi fréquemment. Je recommanderais cependant de faire d'abord des repères ou de sortir du rendu plus tôt. Les appels de rendu répétés Typography ne devraient pas être si mauvais.

L'encapsulation des composants avec React.memo fonctionne bien pour tout ce qui n'a pas d'enfants. J'ai un formulaire avec 3 ExpansionPanel et 14 FormControl et il est à la traîne sur le bureau.

Sans solution à ces problèmes de performances, je ne pourrai pas continuer à utiliser material-ui :s

@prevostc, il est difficile de dire ce qui ne va pas sans un exemple.

@prevostc sans voir une reproduction de codesandbox, ni nous ni vous ne pouvez savoir si cela est même lié à ce problème

@prevostc Créez vos propres composants qui ne nécessitent pas d'enfants que vous pouvez ensuite mémoriser.

c'est-à-dire créez votre propre composant pur/memoed MyExpansionPanel qui prend les accessoires de données/d'événement mais pas les enfants et est responsable du rendu d'un seul panneau d'extension. Ensuite, utilisez ce <MyExpansionPanel ... /> pour rendre chacun de vos panneaux d'extension. Ensuite, les rendus seront limités à un seul panneau d'extension (ou deux lors de la transition entre deux).

@oliviertassinari @kof @dantman
Voici une reproduction codesandbox de mon problème de performances : https://codesandbox.io/s/yvv2y2zxxx

Il s'agit d'un formulaire avec environ 20 champs (ce qui n'est pas rare), vous rencontrerez un certain décalage lors de la saisie de l'utilisateur. Sur les appareils plus lents, ce formulaire n'est tout simplement pas utilisable.

Le problème de performances vient du re-rendu massif sur l'entrée de l'utilisateur, mais l'encapsulation des composants MUI dans un composant pur (React.memo) ne fait rien car tout ici a des enfants et des enfants, cela forcera le re-rendu AFAIK (source : https:// reactjs.org/docs/react-api.html#reactpurecomponent)

Vous trouverez ci-dessous quelques captures d'écran de mon benchmark manuel, une sans aucune optimisation, une avec tout mémorisé et une utilisant un composant d'entrée personnalisé avec un état local pour éviter de définir trop souvent l'état sur l'ensemble du formulaire.
Sur chaque configuration, un rapprochement des entrées utilisateur prend environ 60 ms (bien au-dessus des 16 ms dont j'ai besoin pour un rendu à 60 ips.

Veuillez noter que j'apprendrais avec plaisir que j'ai fait quelque chose de mal parce que j'adore MUI et je serais triste s'il n'y avait pas de solution facile <3

@dantman Comment pouvez-vous écrire un ExpansionPanel qui ne prend aucun React.ReactNode en entrée (enfants ou accessoires) ? Si vous voulez dire que je dois écrire un composant spécifique pour chaque panneau de mon application, ce n'est malheureusement pas possible, j'en ai trop.

screenshot 2018-12-20 at 22 04 08

screenshot 2018-12-20 at 21 56 57

screenshot 2018-12-20 at 22 05 00

@dantman Comment pouvez-vous écrire un ExpansionPanel qui ne prend aucun React.ReactNode en entrée (enfants ou accessoires) ? Si vous voulez dire que je dois écrire un composant spécifique pour chaque panneau de mon application, ce n'est malheureusement pas possible, j'en ai trop.

Oui, au lieu de créer un seul composant massif avec un arbre de panneaux profondément imbriqué, séparez les pièces du panneau d'extension en composants. Il est impossible d'optimiser des arbres massifs comme ça.

Ce n'est pas impossible. Les composants React sont très légers. Copiez et collez un bloc de code d'un composant massif dans une fonction et vous avez presque terminé, après cela, vous n'avez plus qu'à connecter les accessoires. Et tant que vous React.memo cette fonction et évitez de passer des choses qui cassent l'optimisation pure des accessoires, alors les choses sont optimisées assez facilement.

N'oubliez pas que si vous créez un petit composant, vous devez séparer une partie d'un énorme composant. Il ne doit pas nécessairement s'agir de quelque chose de complexe avec son propre fichier et sa propre validation d'accessoires. Il peut s'agir d'un simple composant fonctionnel dans le même fichier que le composant dans lequel il est utilisé sans propTypes. c'est-à-dire que vous pouvez créer de petits composants qui ne sont disponibles que pour le composant dans le même fichier qu'eux.

Oui, Material UI est un peu plus lent que les éléments dom de bas niveau. Mais même si un MUI Input était 10 fois plus lent qu'un input brut et que les choses devenaient trop lentes après 100. Alors vous avez toujours un problème même sans MUI car même si c'est 10 fois plus rapide le input brut

@prevostc Voici votre démo optimisée en divisant le panneau d'extension en un petit composant du même fichier. Comme vous pouvez le voir, un seul panneau d'extension est restitué lorsqu'une entrée est mise à jour. Le temps n'est pas perdu à restituer des panneaux d'extension sans rapport. Si je voulais, je pourrais même faire quelque chose de similaire aux entrées qui partagent un modèle similaire, ce qui entraînerait des entrées non liées non plus restituées.

Je noterai que ce n'est pas seulement un bon modèle d'optimisation, c'est un bon modèle de codage. Dans le code réel, où vous ne créez pas un tableau d'entrées mais les écrivez explicitement avec des noms, des étiquettes et des objectifs définis. Trouver des limites et répéter des modèles optimise non seulement les choses, mais réduit également le passe-partout, rendant le code plus SEC et lisible. c'est-à-dire qu'au lieu de InputWrapper je briserais probablement ce combo FormControl+InputLabel+FormHelperText+Input en un petit composant SimpleTextInput local. Ce qui non seulement l'optimiserait (entraînant des entrées non liées et non pas un nouveau rendu), mais signifierait également que le code n'a pas besoin de répéter le passe-partout supplémentaire.

https://codesandbox.io/s/0o7vw76wzp

screen shot 2018-12-20 at 2 51 31 pm

En lisant ceci, je suis arrivé à la conclusion que pour optimiser mui, vous devez créer des composants spécifiques plus petits. C'est quelque chose que j'ai déjà réalisé et essayé avec succès. Cependant, j'ai également compris qu'il n'y a aucun moyen d'optimiser les composants de la liste car l'API contextuelle modifie tous les accessoires d'entrée.

Salutations

Ok voici un test de résistance mis à jour https://codesandbox.io/s/wz7yy1kvqk

Je suis d'accord avec @dantman sur ce point générique https://github.com/mui-org/material-ui/issues/10778#issuecomment -449153635 MAIS je ne m'attendais pas à un tel problème de performances avec cette faible quantité de composants, mais supportez moi car j'ai trouvé la source de mon problème de performance.

JSS est-il lent ? (alerte spoiler : non)

En référence à certains des commentaires précédents de ce fil, j'ai ajouté une case à cocher dans le test de résistance pour supprimer tous les appels à withStyles et je suis arrivé à la conclusion que JSS est rapide et que ce n'est pas la source du problème de perf (comme @kof l'a souligné dans https://github.com/mui-org/material-ui/issues/10778#issuecomment-396609276).

screenshot 2018-12-22 at 15 17 26

Le correctif

Pour mon cas d'utilisation spécifique, j'ai pu identifier le problème étant que chaque entrée de formulaire a été restituée lors de la mise à jour du formulaire, même si une seule entrée a réellement changé.
Dans la capture d'écran ci-dessous, j'ai enveloppé à la fois FormControl et Input dans un composant mémorisé, évitant le rendu si la valeur ne changeait pas. @dantman m'a en fait suggéré de créer un composant spécifique pour chaque ExpansionPanel mais c'est une solution beaucoup moins générique. En passant, chaque panneau est toujours re-rendu et les performances sont loin d'être optimales mais elles sont suffisantes pour le moment.

screenshot 2018-12-22 at 15 18 22

Donc? Et après?

Je pense qu'il n'y a aucun moyen d'éviter ce genre de problèmes avec une modification du code material-ui sans une modification massive de l'API actuelle fortement basée sur la composition de React.ReactNode .
Mais comme @dantman mentionné dans https://github.com/mui-org/material-ui/issues/10778#issuecomment -449153635, MUI est un peu plus lent que ce qu'il attendait de lui. Ne pas aborder cela du tout est une erreur à mon humble avis.

Étant conscients de ce problème, nous devrons peut-être créer une page de documentation relative aux problèmes de performances et à la manière de les résoudre. Même si sa page redirige principalement vers la doc officielle (https://reactjs.org/docs/optimizing-performance.html) et répertorie les composants qui pourraient causer des problèmes de performances, c'est un début.
Il serait préférable de consoler l'utilisateur lorsqu'un tel problème se produit, mais je n'arrive pas à trouver un moyen de détecter les problèmes au niveau de l'interface utilisateur matérielle.

@prevostc ce message a fait ma journée, c'est le genre de communauté que j'aime. Avez-vous des idées sur ce que mui pourrait changer pour améliorer les performances et éviter le besoin d'optimisations de l'espace utilisateur ? Un changement d'API pourrait être faisable.

je ne :s

Je ne connais pas suffisamment l'interface MUI pour avoir une idée de la façon d'améliorer ses performances brutes (sans changement d'API) pour le moment. Je travaille sur quelques idées mais rien de concluant à ce jour : j'ai une application où un groupe de radio est re-rendu alors que son parent direct ne l'est pas, ne peut pas encore le reproduire localement.

Tout changement d'API consisterait à envisager de supprimer tous les accessoires React.ReactNode de l'API (enfants et autres accessoires comme l'icône, etc.), mais je n'ai pas trouvé de bon moyen de conserver la même configuration.
Voici ce que j'ai essayé : https://codesandbox.io/s/jpw36jw65 (attention : pas fini).

Il est également important de noter que MUI est particulièrement lent en mode développement, car la réaction est particulièrement lente en mode développement. Je ne sais pas s'il y a moyen d'améliorer ça.

Y a-t-il des progrès dans l'ajout de fonctionnalités (comme celle suggérée par @Bessonov ) afin d'optimiser les problèmes de performances auxquels Material-UI est actuellement confronté ?
Lorsque nous avons commencé à utiliser cette excellente bibliothèque pour notre projet, je ne savais pas que de tels problèmes de performances pouvaient survenir lorsque le projet devenait de plus en plus volumineux ; De plus, je n'ai vu aucune section dans les documents Material-UI m'informant des cas pouvant ralentir Material-UI et nuire à l'UX.
De nombreux problèmes de performances - directement ou indirectement liés à Material-UI - sont signalés dans ce numéro. Je pense que ce serait une bonne idée de les énumérer dans un autre numéro afin que chacun puisse suivre les progrès. Si vous pensez que c'est OK, je peux ouvrir un nouveau problème.

@ mkermani144 Nous n'avons pas encore vu de rapport de performance directement corrélé à quelque chose que Material-UI fait mal. Jusqu'à présent, ce numéro a été utilisé comme forum d'aide pour les personnes en difficulté. Confirmez-vous qu'aucune action n'a été signalée ? Je vais énoncer une évidence, l' abstraction React a un coût . Chaque composant enveloppant un hôte ajoutera du poids à votre arbre de rendu, cela le ralentira. Bien que vous puissiez rendre plus de 100 éléments de liste avec un hôte natif, cela commence à poser problème lorsque vous les enveloppez avec un composant de classe. Ce n'est pas spécifique à Material-UI.

Table

Mode de développement

Prenons l'exemple d'un tableau. C'est un composant que les gens trouvent lent. Nous avons documenté la virtualisation , cela aide beaucoup.

Dans le cas de test suivant, nous rendons 100 éléments en mode dev . On peut considérer les cas suivants :

  1. Tableau Raw : https://codesandbox.io/s/v066y5q7z3 : 63ms dans le rendu
  2. Table Material-UI Master : https://codesandbox.io/s/m4kwmvj9ly : 250ms dans le rendu
  3. Table Material-UI Suivant : https://codesandbox.io/s/2o35yny1jn : 262ms dans le rendu

Ainsi, le surcoût lié à l'utilisation de Material-UI en mode dev sur l'élément hôte est d'environ x4 (la différence est plus petite en production !), simplement parce que nous créons des composants intermédiaires. C'est pourquoi la virtualisation commence à être importante après le rendu d'une liste d'environ 100 éléments de table. Maintenant, nous pouvons plonger un peu dans Pourquoi et que pouvons-nous faire à ce sujet ?

  1. Table Raw + composant de fonction. Pourquoi un composant fonctionnel ? Nous voulons faire abstraction des noms de classe utilisés. Nous ne voulons pas que les utilisateurs du composant les répètent.
    https://codesandbox.io/s/1zl75mwlpj : 105ms dans le rendu
  2. Table Raw + composant de fonction + forwardRef. Pourquoi forwardRef ? Nous voulons que le composant soit "transparent", pouvant accéder à l'élément hôte avec une ref.
    https://codesandbox.io/s/32o2y0o9op : 120ms dans le rendu
  3. Table Raw + composant de fonction + forwardRef + withStyles. Pourquoi avec Styles ? Parce que nous voulons styliser notre composant :
    https://codesandbox.io/s/j2n6pv768y : 200ms dans le rendu
  4. Table Raw + composant de fonction + forwardRef + makeStyles. makeStyles peut être plus rapide que withStyles, essayons :
    https://codesandbox.io/s/yw52n07l3z : 130ms dans le rendu.

Nous avons donc un levier disponible : migrer tous les composants de withStyles vers makeStyles. On peut gagner environ +30% de performances (262 / (262 - 70)) en mode dev .

Mode de fabrication

J'ai exécuté les mêmes cas de test en mode production :

  • n°1 30ms dans l'hydrate
  • n°3 106ms dans l'hydrate
  • n°4 40ms dans l'hydrate
  • n°5 41ms dans l'hydrate
  • n°6 80ms dans l'hydrate
  • n°7 57ms dans l'hydrate

Ainsi, la migration de withStyles à makeStyles est toujours une accélération de +30% en théorie en mode production .

Si vous pensez que c'est OK, je peux ouvrir un nouveau problème.

@ mkermani144 Si vous avez un cas spécifique où Material-UI le fait mal, bien sûr.

J'ai lu tous les commentaires sous ce numéro. Mon problème ne correspond à aucun des autres problèmes mentionnés précédemment.

J'ai un composant List contenant quelques ListItem s, dont l'un est sélectionné et mis en surbrillance. Lorsque je clique sur un autre ListItem pour le sélectionner et le mettre en surbrillance, toute la liste (contenant ses enfants) est à nouveau rendue.

Je sais que ce problème peut sembler exactement le même qu'un commentaire précédent , mais ce n'est pas le cas ; au moins je le pense.

Regardons les résultats du profileur React :

image
Comme vous pouvez le voir, j'ai un composant MyList au niveau supérieur de l'image. Ce composant n'est qu'un wrapper autour de MUI List et le rend simplement pur, c'est-à-dire :

class MyList extends React.PureComponent {
  render() {
    return (
      <List>
        {this.props.children}
      </List>
    );
  }
}

J'ai ajouté ce wrapper parce que @eps1lon dans l' un de ses commentaires mentionnait que le re-rendu de List provoque la mise à jour du contexte, et cette mise à jour du contexte oblige tous les consommateurs (y compris ListItem s) à re-rendu également .

J'ai également essayé de rendre tous mes ListItem purs et de profiler à nouveau l'application. Les résultats étaient les mêmes, sauf que mon composant personnalisé (c'est- MyListItem dire

Je sais que le problème se produit parce que le contexte que MUI utilise pour le style restitue _d'une certaine manière_. Mais je ne sais pas pourquoi ce re-rendu se produit et comment je peux l'éviter.

Ou est-ce que je fais quelque chose de mal ?

Remarque : j'utilise la nouvelle solution de style MUI (alpha), c'est-à-dire @material-ui/styles . Je ne sais pas si cela compte.

@ mkermani144 Supprimez Material-UI avec des éléments natifs, observez que le re-rendu est toujours présent. La logique pure n'aidera pas comme ça. React.createElement crée de nouvelles références à chaque rendu, il invalide votre PureComponent.

Oui, je sais que les éléments sont des objets et que les objets ne sont pas strictement égaux en Javascript, donc sCU échoue.

Mais je ne comprends pas ce que vous voulez dire lorsque vous dites que React.createElement est à nouveau appelé. Quel appel à createElement ? Si vous voulez dire les appels à l'intérieur de List , il n'appelle que createElement pour ses enfants ( ListItem s) uniquement s'il est re-rendu. S'il n'est pas re-rendu, aucun createElement ne sera appelé et aucun re-rendu ne devrait se produire. Le problème est que le List lui-même est re-rendu.

@ mkermani144 Si vous pouvez créer un exemple de reproduction minimale, nous pouvons l'examiner.

Votre MyList (et donc List ) est rendu à nouveau à cause du composant qui rend MyList (appelons-le MyComponent ) est rendu à nouveau. PureComponent sur MyList n'aide pas car MyComponent ont été restitués et ont créé de nouveaux enfants pour MyList afin que la vérification de MyList échoue.

Votre MyComponent probablement restitué car c'est là que vous stockez l'état de l'élément sélectionné.

Je pense que l'implémentation MUI de List devrait changer pour ne pas recréer la valeur de contexte List à chaque rendu
ici : https://github.com/mui-org/material-ui/blob/fb4889f42613b05220c49f8fc361451066989328/packages/material-ui/src/List/List.js#L57

Donc, à la place, faites en sorte que List ressemble à ceci :

const List = React.forwardRef(function List(props, ref) {
  const {
    children,
    classes,
    className,
    component: Component,
    dense,
    disablePadding,
    subheader,
    ...other
  } = props;
  const context = React.useMemo(() => ({ dense }), [dense]);

  return (
    <Component
      className={clsx(
        classes.root,
        {
          [classes.dense]: dense && !disablePadding,
          [classes.padding]: !disablePadding,
          [classes.subheader]: subheader,
        },
        className,
      )}
      ref={ref}
      {...other}
    >
      <ListContext.Provider value={context}>
        {subheader}
        {children}
      </ListContext.Provider>
    </Component>
  );
});

Cela simplifierait la création sCU versions

Votre MyList (et donc List) est rendue à nouveau car le composant qui rend MyList (appelons-le MyComponent) est rendu à nouveau. PureComponent sur MyList n'aide pas car MyComponent a été rendu à nouveau et a créé de nouveaux enfants pour MyList afin que la vérification de MyLists échoue.

@Pajn Non, regardez les résultats de mon MyList n'a pas refait le rendu (c'est gris), mais List fait (c'est bleu). Je ne persiste pas sur PureComponent pour MyList . Même si j'implémente sCU pour MyList afin qu'il ne soit pas re-rendu, List __fait un re-rendu__.

@oliviertassinari
J'ai créé un exemple de reproduction minimale :

import React, { Component } from 'react';

import StylesProvider from '@material-ui/styles/StylesProvider';
import ThemeProvider from '@material-ui/styles/ThemeProvider';

import { createMuiTheme } from '@material-ui/core';

import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';

const theme = createMuiTheme({});

const MyListItem = React.memo(ListItem, (prev, next) => prev.selected === next.selected);

class App extends Component {
  state = {
    selected: null,
  }
  render() {
    return (
      <StylesProvider>
        <ThemeProvider theme={theme}>
          <List>
            {[0, 1, 2, 3, 4].map(el => (
              <MyListItem
                button
                selected={el === this.state.selected}
                onClick={() => this.setState({ selected: el })}
              >
                {el}
              </MyListItem>
            ))}
          </List>
        </ThemeProvider>
      </StylesProvider>
    );
  }
}

export default App;

Résultats du profileur React (après avoir cliqué sur le 4ème élément de la liste) :

image

Comme vous pouvez le voir, cela fonctionne comme prévu, c'est-à-dire qu'il n'y a pas de rendus supplémentaires (sauf pour les composants ButtonBase dans les ListItem s). Le problème est que, cette reproduction est _trop minimale_; il y a beaucoup de choses que je saute dedans.

Je sais que vous ne pouvez pas me dire ce qui ne va pas avec mon code provoquant des rendus supplémentaires. Mais je vous pose une question : qu'est-ce qui peut provoquer un re-rendu dans les composants WithStylesInner qui enveloppent les composants MUI ?

@ mkermani144 Que pensez-vous de ce correctif ?

--- a/packages/material-ui/src/List/List.js
+++ b/packages/material-ui/src/List/List.js
@@ -40,6 +40,13 @@ const List = React.forwardRef(function List(props, ref) {
     ...other
   } = props;

+  const context = React.useMemo(
+    () => ({
+      dense,
+    }),
+    [dense],
+  );
+
   return (
     <Component
       className={clsx(
@@ -54,7 +61,7 @@ const List = React.forwardRef(function List(props, ref) {
       ref={ref}
       {...other}
     >
-      <ListContext.Provider value={{ dense }}>
+      <ListContext.Provider value={context}>
         {subheader}
         {children}
       </ListContext.Provider>

Voulez-vous soumettre une demande de tirage ? :) Nous utilisons la même stratégie avec le composant Table. Cela fonctionne très bien. Merci d'avoir signalé le problème !

@oliviertassinari Bien sûr. C'est exactement ce que @Pajn a suggéré plus tôt. J'ai soumis un PR .

14934 est fusionné ; le composant List , cependant, peut devenir un goulot d'étranglement des performances s'il est suffisamment grand, peu importe à quel point il est optimisé. Ne devrions-nous pas fournir un exemple montrant l'utilisation de react-window ou react-virtualized avec le composant List , comme celui que nous avons dans les documents Table ?

Ne devrions-nous pas fournir un exemple montrant l'utilisation de la fenêtre de réaction ou de la virtualisation de réaction avec le composant List, comme celui que nous avons dans les documents de table ?

Ce serait super :+1:

Fwiw, j'ai construit une application de chat et l'application doit afficher une grande liste de contacts. je suis tombé sur le même problème
@ mkermani144 avait.

https://stackoverflow.com/questions/55969987/why-do-the-children-nodes-rerender-when-the-parent-node-is-not-even-being-update/55971559

@henrylearn2rock Avez-vous envisagé d'utiliser la virtualisation ? Nous avons ajouté une démo pour la liste : https://next.material-ui.com/demos/lists/#virtualized -list.

Cela aussi m'a vraiment fait trébucher. Je pense que la plupart des gens (y compris moi) supposaient que tout sous un composant pur était à l'abri d'un rendu, ce qui n'est évidemment pas le cas pour cette bibliothèque. Je vais essayer la virtualisation comme vous l'avez suggéré récemment. Merci!

Je pense que la plupart des gens (y compris moi) supposaient que tout sous un composant pur était à l'abri d'un rendu, ce qui n'est évidemment pas le cas pour cette bibliothèque.

Ce n'est pas ainsi que fonctionne React.PureComponent ou React.memo. Cela n'affecte que le composant lui-même. Les enfants devront peut-être encore refaire le rendu si le contexte change.

@pytyl Pouvez-vous partager le code dans lequel vous avez utilisé un PureComponent et vous vous attendiez à ce qu'il empêche tout nouveau rendu dans son sous-arbre ?

@ eps1lon la documentation suivante donne l'impression que le renvoi de false à partir de shouldComponentUpdate ignore automatiquement le ré-rendu dans les composants enfants.
https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate -in-action

Étant donné que shouldComponentUpdate a renvoyé false pour le sous-arbre enraciné en C2, React n'a pas tenté de rendre C2 et n'a donc même pas eu à invoquer shouldComponentUpdate sur C4 et C5.

Peut-être que je me trompe là-dessus ? Ce qui suit est un instantané de mon profileur. Juste pour le plaisir de tester, je retourne explicitement false pour shouldComponentUpdate dans mon composant Menu :

Screen Shot 2019-05-08 at 7 46 32 PM

Cela a rendu tous mes composants enfants (Categories, Category, CategoryItems, CategoryItem) non rendus. De nombreux éléments liés à l'interface MUI semblent être restitués en bas, ce qui semble causer beaucoup de retard. Des trucs comme avec Styles, Typographie, ButtonBase. Encore un peu nouveau pour React alors veuillez excuser mon ignorance. Vous trouverez ci-dessous mon code pour le composant Menu (où je renvoie false pour shouldComponentUpdate):

import React, { Component } from "react";
import Categories from "./Categories";
import { withStyles, Paper } from "@material-ui/core";

const styles = theme => ({
  root: {
    paddingTop: 0,
    marginLeft: theme.spacing.unit * 2,
    marginRight: theme.spacing.unit * 2,
    marginTop: theme.spacing.unit * 1
  }
});

class Menu extends Component {
  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.categories.length == this.props.categories.length) {
      return false;
    }
    return true;
  }

  render() {
    const { classes, categories } = this.props;

    return (
      <Paper className={classes.root}>
        <Categories categories={categories} />
      </Paper>
    );
  }
}

export default withStyles(styles)(Menu);

J'aurais besoin d'un codeandbox complet pour comprendre le problème.

@eps1lon Je vais essayer d'en produire un pour demain. Merci.

@eps1lon voici le codepen :
https://codesandbox.io/s/348kwwymj5

Brève description
C'est une application de menu de base pour les restaurants (qui ont souvent plus de 100 éléments de menu). Lorsque l'utilisateur clique sur un élément de menu, il ouvre une boîte de dialogue « Ajouter à la commande ». Je joindrai quelques situations où le profileur montre des performances médiocres (ces statistiques ne concernent pas une version de production).

Système
MacBook Pro (Retina, 13 pouces, début 2015)
Intel Core i7 à 3,1 GHz
Firefox 66.0.3

Cas 1 (l'utilisateur clique sur un élément de menu)
Durée de rendu : 218 ms

Screen Shot 2019-05-10 at 4 45 26 AM

Screen Shot 2019-05-10 at 4 45 48 AM

Cas 2 (l'utilisateur clique sur le bouton Ajouter à la commande dans la boîte de dialogue)
Durée de rendu : 356 ms

Screen Shot 2019-05-10 at 4 46 24 AM

Screen Shot 2019-05-10 at 4 47 10 AM

Je suis sûr que je fais une erreur de novice ici, donc tout conseil est grandement apprécié.

Comme WithStyles(ButtonBase) est restitué, je suppose que WithStyles utilise un contexte qui est recréé même s'il n'en a pas besoin.

J'ai réussi à trouver ceci https://github.com/mui-org/material-ui/blob/048c9ced0258f38aa38d95d9f1cfa4c7b993a6a5/packages/material-ui-styles/src/StylesProvider/StylesProvider.js#L38 mais je ne trouve pas d'endroit où StylesProvider est utilisé dans le code réel (la recherche GitHubs n'est pas très bonne) mais cela pourrait être la raison.

@eps1lon sait-il si cela peut en être la cause ? Si c'est le cas, un useMemo sur l'objet de contexte résoudrait probablement ce problème. Bien que je ne sache pas si localOptions est stable ou si useMemo doit être propagé encore plus loin.

Peut-être. Mais vous devez d'abord rechercher pourquoi votre composant utilisant un StylesProvider effectue un rendu. Il s'agit soit de quelque chose au sommet de votre arbre, soit d'une limite d'interface utilisateur. Dans les deux cas, ceux-ci devraient rarement être restitués. N'oubliez pas que le contexte de réaction n'est de toute façon pas optimisé pour les mises à jour fréquentes.

Nous ne devrions pas optimiser prématurément ces choses simplement parce qu'un objet est recréé pendant le rendu. La mémorisation n'est pas une solution miracle. Donc sans exemple concret je ne peux pas faire grand chose. Oui, les choses sont restituées. Parfois plus souvent qu'ils n'en ont besoin. Mais un re-rendu gaspillé ne signifie pas que c'est la cause d'un goulot d'étranglement des performances.

@pytyl J'ai regardé votre codesandbox, il y a un problème avec l'architecture de rendu. Vous restituez tout lorsque vous cliquez sur l'élément de menu. Votre GlobalContext saute la logique pure.

@ eps1lon Je pense que nous devrions clore ce problème. Il serait préférable de se concentrer sur des problèmes spécifiquement identifiés.

TL; DR : Créer des tranches de contexte, mémoriser les valeurs de contexte, aucun problème avec l'interface matérielle en particulier : https://codesandbox.io/s/8lx6vk2978

J'ai creusé et le problème est que vous avez ce grand contexte global qui est recréé pendant le rendu. Vous restituez votre application lorsque vous cliquez sur le point auquel le contexte global est recréé. Votre CategoryItem l'écoute qui apparaît 100 fois dans votre App. Puisque vous avez 100 éléments de menu matériel-ui, vous rencontrez la mort classique par mille coupures.

Donc, ironiquement, une partie de la solution consiste à mémoriser une valeur de contexte, mais la partie importante consiste à identifier des tranches de contexte distinctes. Il semble qu'un contexte d'état et de répartition soit approprié. Ceci est recommandé lors de l'utilisation de useContext avec useReducer et semble convenir ici.

Cela peut créer un arbre assez grand et rendre les accessoires infernaux plus vous avez de contextes. Je vous encourage à jeter un œil à useContext . Cela vous aidera beaucoup si vous commencez à faire face à ces problèmes.

@oliviertassinari C'est une bonne question de collecter les pièges courants avec des solutions. Nous pouvons décider si nous voulons créer des problèmes distincts à partir de celui-ci.

@oliviertassinari @eps1lon merci pour la révision ! Les performances semblent excellentes.

J'ai juste eu un problème avec les performances de rendu lent. Je l'ai entièrement résolu en remplaçant toutes les instances du composant <Box> par <div> s. J'ai débogué en utilisant le flamegraph de react devtools, et je suis passé d'environ 420 ms à 20 ms.

Avec <Box> es;
Screen Shot 2019-08-16 at 12 47 25 AM

Sans <Box> es :
Screen Shot 2019-08-16 at 12 42 38 AM

@mankittens Vous pouvez conserver le composant Box, en utilisant des composants https://github.com/mui-org/material-ui/pull/16858.

Je clos ce sujet. Nous avons besoin d'un rapport de performance dédié pour chaque domaine d'amélioration potentiel, et non d'un fil conducteur.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

anthony-dandrea picture anthony-dandrea  ·  3Commentaires

chris-hinds picture chris-hinds  ·  3Commentaires

rbozan picture rbozan  ·  3Commentaires

newoga picture newoga  ·  3Commentaires

sys13 picture sys13  ·  3Commentaires