【问题标题】:React setState takes 200ms+反应 setState 需要 200 毫秒+
【发布时间】:2022-06-13 22:19:46
【问题描述】:

我正在监听每秒触发一次回调的 websocket:

setState1 每秒发生一次,setState2 也在 10 秒后每秒发生一次,并允许 LargeChildComponent 显示。

我发现更新此状态的时间超过 200 毫秒。

const myWebsocketCallback = async(newData) => {
  dataRef.current = [...dataRef.current, newData]

  const start = performance.now()
  setDataState(dataRef.current)
  console.log('setState', performance.now() - start)

  doWorkWithNewData()
}

所以设置状态一开始很慢,当LargeChildComponent正在渲染时特别慢。


我发现将大型 JSON 对象从状态初始化移动到 init useEffect() 大大减少了该时间。

- const [myBigData, setMyBigData] = useState(VERY_LARGE_JSON_OBJECT)

+ const [myBigData, setMyBigData] = useState()
+ useEffect(() => {
+   setMyBigData(VERY_LARGE_JSON_OBJECT)
+ }, [])

每次渲染都会检查默认状态值吗?我应该在 useEffect(myFunc, []) 中初始化状态吗?


仅上述更改就取得了巨大的改进。

但是,setState() 仍然需要 80 毫秒以上,而且它似乎取决于渲染的大小(子组件)。

我的印象是 setState() 是一个 async 任务,应该很快发生,无论任何依赖它的组件。

为什么更新状态仍然需要 80 毫秒?

是因为在回调函数中吗?状态是否真的在等待孩子渲染?

【问题讨论】:

  • 试试useState(() => very_large_object)。您可能会看到在每次渲染时实际分配和销毁该大对象的副作用,即使它只需要在第一次渲染时初始化状态。将工厂方法传递给 useState 避免了在每次渲染时进行昂贵的初始化的不必要成本。
  • @Brandon 感谢您的建议。我不知道这是一个选项,并且似乎与 init useEffect 方法具有相同的效果。关于第二部分的任何想法,它仍然很慢,大约 80 毫秒?

标签: reactjs performance asynchronous state


【解决方案1】:

只要你在 React 生命周期方法(React 事件处理程序或渲染函数或效果)之外调用 setState,它就会阻塞,而 React 会重新渲染所有内容。在 React 18 中,他们正在更改状态更改和渲染的批处理方式。

您可以:

更新到 React 18 createRoot 以获得自动批处理


import ReactDOM from "react-dom";
import App from 'App';

const container = document.getElementById('root');

// Create a root.
const root = ReactDOM.createRoot(container);

// Initial render
root.render(<App name="Saeloun blog" />);

// During an update, there is no need to pass the container again
root.render(<App name="Saeloun testimonials" />);

或者在React中使用unstable_batchUpdate方法

import { unstable_batchedUpdates } from 'react-dom'

const myWebsocketCallback = async(newData) => {
  dataRef.current = [...dataRef.current, newData]

  const start = performance.now()
  unstable_batchUpdates(() => {
    setDataState(dataRef.current)
  })
  console.log('setState', performance.now() - start)

  doWorkWithNewData()
}


【讨论】:

    猜你喜欢
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多