Maison > Questions et réponses > le corps du texte
useEffect(() => { console.log("render"); }); const handleClick = () => { setC1((c) => c + 1); Promise.resolve().then(() => { setC1((c) => c + 1); }); }; const handleClick2 = () => { Promise.resolve().then(() => { setC1((c) => c + 1); }); setC1((c) => c + 1); };
Dans la version React18, pourquoi un seul rendu se produit en cliquant sur la méthode handleClick
方法会出现两次渲染,而点击handleClick2
?
Je veux que le résultat des deux méthodes soit le même. Quelqu'un peut-il me dire pourquoi ils sont différents ?
P粉6429205222023-09-08 17:06:21
Je vais vous expliquer en quoi ces séquences d'appels diffèrent et comment le comportement observé est possible.
Je ne peux pas vous dire exactement comment les mises à jour de React se présentent par lots en interne, Je suppose simplement que React propose des optimisations complexes qui ne sont pas pertinentes pour le développeur utilisant React et nécessitent une compréhension approfondie des composants internes de React et peut-être même un changement d'une version à l'autre. (N'hésitez pas à me corriger.)
Promise.resolve()
安排一个新的微任务,实际上相当于 window.queueMicrotask()
.
setState
(éventuellement) planifiera également une nouvelle microtâche,
Par conséquent leurs rappels (Promise
和 setState
Promise et
La différence entre ces deux variantes est
handleClickA
中,在两个 updater
函数之间调用 setState2
s'accroche handleClickB
中,两个 updater
Les fonctions de J'ai légèrement réécrit votre code pour mieux illustrer la séquence d'appel :
const setState1 = setState; const setState2 = setState; const update1 = updaterFunction; // c => c + 1 const update2 = updaterFunction; // c => c + 1 const handleClickA = () => { // Scheduled functions: setState1( update1 ); // 1. --> [ update1 ] queueMicrotask(() => { // 2. --> [ update1, setState2 ] setState2( update2 ); // 4. --> [ update2 ] }); // update1(); // 3. --> [ setState2 ] // setState2( update2 ); // 4. --> [ update2 ] // update2(); // 5. --> [] }; const handleClickB = () => { // Scheduled functions: queueMicrotask(() => { // 1. --> [ setState2 ] setState2( update2 ); // 3. --> [ update2 ] }); setState1( update1 ); // 2. --> [ setState2, update1 ] // setState2( update2 ); // 3. --> [ update1, update2 ] // update1(); // 4. --> [ update2 ] // update2(); // 5. --> [] };
Ici, j'explique la séquence d'appel.
(FIFO
>):
handleClickA
// 0. --> [] - schedule update1 (setState1()) // 1. --> [ update1 ] - schedule setState2 // 2. --> [ update1, setState2 ] - invoke update1() // 3. --> [ setState2 ] - schedule update2 (setState2()) // 4. --> [ update2 ] - invoke update2() // 5. --> []
handleClickB
:// 0. --> [] schedule setState2 // 1. --> [ setState2 ] schedule update1 (setState1()) // 2. --> [ setState2, update1 ] schedule update2 (setState2()) // 3. --> [ update1, update2 ] invoke update1() // 4. --> [ update2 ] invoke update2() // 5. --> []
updater
Je suppose que React essaie de regrouper toutes les
c'est-à-dire que chaque fois que seule la fonction de mise à jour est appelée, essayez de les regrouper et de ne mettre à jour l'état final qu'une seule fois. Cependant, si une nouvelle
fonction est appelée, React peutterminer la boucle de mise à jour actuellesetState
et démarrer un nouveau cycle de rendu avant d'appeler la prochaine fonction updater.
Je ne peux que deviner pourquoi cela est fait代码>
Parce que le nouveau
pourrait casser le lot d'une manière ou d'une autre, ousetState
appels sont effectués de manière récursive, le prochain rendu sera trop retardé, ou setState