React hooks:为什么异步函数中的多个 useState setter 会导致多次重新渲染? [英] React hooks: Why do several useState setters in an async function cause several rerenders?

查看:18
本文介绍了React hooks:为什么异步函数中的多个 useState setter 会导致多次重新渲染?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下 onClick 回调函数将导致 1 次重新渲染:

This following onClick callback function will cause 1 re-render:

const handleClickSync = () => {
  // Order of setters doesn't matter - React lumps all state changes together
  // The result is one single re-rendering
  setValue("two");
  setIsCondition(true);
  setNumber(2);
};

React 将所有三个状态更改集中在一起并导致 1 次重新渲染.

React lumps all three state changes together and causes 1 rerender.

但是,以下 onClick 回调函数将导致 3 次重新渲染:

The following onClick callback function, however, will cause 3 re-renderings:

const handleClickAsync = () => {
  setTimeout(() => {
    // Inside of an async function (here: setTimeout) the order of setter functions matters.
    setValue("two");
    setIsCondition(true);
    setNumber(2);
  });
};

这是对每个 useState setter 的重新渲染.此外,setter 的顺序会影响每个渲染中的值.

It's one re-render for every useState setter. Furthermore the order of the setters influences the values in each of these renderings.

问题:为什么我使函数异步(此处通过 setTimeout)会导致状态更改一个接一个地发生,从而导致 3呈现.如果函数是同步的,只导致一次重新渲染,为什么 React 会将这些状态变化混为一谈?

Question: Why does the fact that I make the function async (here via setTimeout) cause the state changes to happen one after the other and thereby causing 3 re-renders. Why does React lump these state changes together if the function is synchronous to only cause one rerender?

您可以使用 这个 CodeSandBox 来体验行为.

You can play around with this CodeSandBox to experience the behavior.

推荐答案

如果代码在 react 内部开始执行(例如,onClick 侦听器或 useEffect),则react 可以确保在您完成所有状态设置后,执行将返回 react 并且可以从那里继续.所以对于这些情况,可以让代码继续执行,等待返回,然后同步做一次渲染.

If code execution starts inside of react (eg, an onClick listener or a useEffect), then react can be sure that after you've done all your state-setting, execution will return to react and it can continue from there. So for these cases, it can let code execution continue, wait for the return, and then synchronously do a single render.

但如果代码执行随机开始(例如,在 setTimeout 中,或通过解析承诺),那么当您完成时代码不会返回以做出反应.所以从 React 的角度来看,它正在安静地睡觉,然后你调用 setState,迫使 React 像啊!他们正在设置状态!我最好渲染".有一些异步方式让 react 可以等待,看看您是否正在做更多事情(例如,超时 0 或微任务),但没有一种同步方式让 react 知道您何时完成.

But if code execution starts randomly (eg, in a setTimeout, or by resolving a promise), then code isn't going to return to react when you're done. So from react's perspective, it was quietly sleeping and then you call setState, forcing react to be like "ahhh! they're setting state! I'd better render". There are async ways that react could wait to see if you're doing anything more (eg, a timeout 0 or a microtask), but there isn't a synchronous way for react to know when you're done.

在当前版本的 react 中,您可以使用 unstable_batchedUpdates 告诉 react 批量更改多个更改:

In the current version of react, you can tell react to batch multiple changes by using unstable_batchedUpdates:

import { unstable_batchedUpdates } from "react-dom";

const handleClickAsync = () => {
  setTimeout(() => {
    unstable_batchedUpdates(() => {
      setValue("two");
      setIsCondition(true);
      setNumber(2);    
    });
  });
};

一旦 react 18 到来,这将是不必要的,因为他们对并发模式的渲染所做的更改将消除对这个的需要.

Once react 18 arrives, this won't be necessary, since the changes they've made to rendering for concurrent mode will get rid of the need for this.

这篇关于React hooks:为什么异步函数中的多个 useState setter 会导致多次重新渲染?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆