Le guide des renders en React

June 23, 202213 min read

banner url

Les render perturbent les développeur React. C'est quoi ? C'est mal ? C'est bien ? Comment les optimisers ?

Tant de questions qui reste sans réponse. Mais dans ce cours article je vais essayé d'y répondre et de vous donner les clés pour maîtriser les renders.

C'est quoi un render ?

Déjà il faut démistifier ce terme : "un render"... ça veut tout et rien dire à la fois. Pourtant le concepts derrière un render est très simple.

C'est juste une réévaluation de la fonction de ton composant. C'est tout. Un render n'est qu'un mot complexe pour définir un concept simple.

Imagine toi une fonction add qui prend deux paramètres et qui retourne la somme de ces deux paramètres.

function add(a, b) {
  return a + b;
}

Quand tu appel add(1, 2) tu run la fonction, tout ce qui est à l'intérieur vas être executé. Bah quand tu "re-render" un composant tu ne fais que d'appeler la fonction.

Le render du composant App c'est comme si tu faisais add(1, 2) ! Car les composants en React ne sont que des functions qui sont appelés afin de render du JSX qui sera par la suite build en HTML et affiché à l'écran.

Mais un render veut-il dire que le DOM vas être changé ou pas ? Pour ça il faut comprendre le ReactDOM ou le VirtualDOM pour mieux comprendre comment il réagit fasse aux changement.

Tu peux en savoir plus en allant regarder cette vidéo mais pour résumer le ReactDOM ne vas pas modifié le DOM si le JSX retourné par un composant est le même que lors du render précédent. On peut légitimement ce demandé quel est alors le problème d'un render ?

Le problème des renders

Quand un render se produit, tu vas consommer des performances de ton navigateur pour récalculé le nouveau JSX, qu'il change ou non.

const generatePrime = (n) => {
  // generate prime number from 0 to n
};

export default function App() {
  // this state is not used, is just to trigger a render
  const [, render] = useReducer((v) => v + 1, 0);

  // we don't show prime number in render
  const prime = generatePrime(10000);

  return (
    <div className="App">
      <button onClick={render}>Render</button>
    </div>
  );
}

Quand tu vas cliquer sur le bouton, tu verra que rien ne change ni dans le DOM, ni dans l'interface... mais les performance sont impacté.

La raison est simple, notre fonction est recalculé juste que le DOM n'a pas besoin d'être modifié car le Virtual DOM va comparer le JSX retourné par la fonction avec le JSX du render précédent et si il est identique il ne vas rien faire.

Mais alors quel est le problème avec les render ?

Justement il n'y en as pas, jusqu'aux moment ou tu fais des choses couteuses dans tes composants. Il est inutile d'essayé d'optimiser les render d'un composant qui n'affiche que du text ou une image. Il ne faut pas essayé d'optimisé les render... Le but est juste d'avoir une application fluide.

Ce battre contre les render est inutile. Les renders sont saint et penser en terme de render est contre productif.

Il faut plutôt penser en terme de performance. Si quand tu clique sur un bouton tu attends 0.5 secondes avant que l'interface réagisse, c'est que tu as un problème de performance. C'est pour ça qu'on va voir ensemble comment optimiser des problèmes de performance via l'optimisation des render.

Comment optimiser les performances ?

Pour optimiser les performances la règle est simple : uniquement les éléments qui change doivent être update. On ne veut pas update la terre entière lors d'un changement de username.

Mais attention, les développeurs ont tendances à utiliser trop souvent les hooks comme useMemo et useCallback.

Je vais te partagé deux technique pour optimiser les render...

Utiliser les children

Faut connaître une règle simple :

Dès qu'un element est render, tous ses enfants sont render aussi.

Non les props n'ont aucun rôle dans le render de nos composants. Prenons un exemple pratique :

const Parent = () => {
  // Call render will provoque a render of Parent and Child
  const [, render] = useState(0);

  return (
    <div>
      <button onClick={() => render((v) => v + 1)}>Render</button>
      <Child />
    </div>
  );
};

<Child />

Mais il y a un cas d'optimisation intéressant c'est de passé Child en props de notre fonction. Prenons un cas plus concret pour comprendre ce use case...

Imaginons un composant qui a un background dynamique lorsque tu bouge ta souris. Plus ta souris est en haut plus le background est clair et plus ta souris est en bas plus le background est foncé.

Evidement on a envie d'avoir des éléments à l'intérieur de ce background. Ici on a un composant <Child /> qui va possédé à l'intérieur un hooks qui permet de calculé le nombre de render qui c'est passé.

Je t'ai mis un playground, je te laisse t'amusé avec et écouté les émojis 🦁 pour optimisé cette application.

Error with component MdxPlayground size

Ce que ta fait faire 🦁 c'est déplacé le composant <Child /> en props de <AnimatedBackground />. Et ce qui est intéressant c'est que tous les enfants d'un composant sont render, mais les props ne sont pas render car React sait quel n'ont pas changé !

Prenons notre démo d'avant avec Parent et Child et fixons le problème !



my profile picture

Écris par Melvyn Malherbe

J'ai aidé 200 personnes à apprendre React et Next.js. Je suis un créateur de contenu et un développeur web. Plus de 2'600 personnes reçoivent mes newsletter par email chaque semaine.

En apprendre plus à propos de moi