【发布时间】: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