[英]With flushSync() inside useEffect do we do the same as using useLayoutEffect?
https://reactjs.org/docs/react-dom.html#flushsync
强制 React同步刷新提供的回调中的任何更新。 这确保了 DOM 立即更新。
// Force this state update to be synchronous.
flushSync(() => {
setCount(count + 1);
});
// By this point, DOM is updated.
知道了,这和使用useLayoutEffect是一样的,还是我理解错了 flushSync() ?
const App = () => {
const [name, setName] = React.useState("Leonardo");
React.useEffect(() => {
ReactDOM.flushSync(() => {
for (let index = 1; index <= 100000; index++) { // for simulate blocking
console.log(index);
}
setName("Jose");
});
});
return (
<div>
<h1>Hello {name}</h1>
</div>
);
};
跟这个一样吗?
React.useLayoutEffect(() => {
for (let index = 1; index <= 100000; index++) {
console.log(index);
}
setName("Jose");
});
useLayoutEffect 对于在绘制 dom 之前或代码导致闪烁时需要发生的事情很有用。 它已经是同步的,并且总是在代码中的每个 useEffect 挂钩之前执行。
flushSync 用于将 setState 转换为同步。 在 99% 的情况下,您将在表单提交处理程序之类的处理程序中使用 flushSync,在 useEffect 之外执行命令式操作
function handleSubmit(values) {
flushSync(() => {
setForm(values);
});
}
请注意 flushSync 会强制重新渲染,因此请谨慎使用
flushSync 的常见用例是在设置 state 后立即更新 DOM。 示例滚动到列表中新添加的元素
flushSync(() => {
setElements((elements) => [
...elements,
{
id: 'random',
},
]);
});
// scroll to element here
检查此示例https://codesandbox.io/s/react-18-batching-updates-flushsync-forked-vlrbq8 。 您可以删除 flushSync 并查看差异
flushSync
用于强制 React 刷新 state 更新,当您尝试将它放在useEffect
中时,它不会影响调用useEffect
的时间,它总是在更改反映在浏览器上之后,而useLayoutEffect
在之前和之前调用这是它们之间的主要区别。
所以flushSync
不是应该在 useEffect 中执行的useEffect
你甚至会收到这个警告
警告:从生命周期方法内部调用了 flushSync。 当 React 已经呈现时,React 无法刷新。 考虑将此调用移至调度程序任务或微任务。
他们不一样。 您的代码可能提供相同的性能、功能和结果,但它们在本质上是不同的。 flushSync
是一个低级别的 API,它绕过正常的调度机制立即将更新刷新到 React DOM。 它应该谨慎使用并且只在必要时使用,因为它会导致性能不佳并且更容易出现错误和不一致。 另一方面, useLayoutEffect
是一个更高级别的挂钩,它安排 DOM 更新在处理完所有其他更新后同步发生。 它通常是确保更新与页面布局同步的首选方法。
我做了这段代码,看看我是否理解了一切,请纠正我:
function App2() {
const [c, setC] = React.useState(0);
const inc1 = () => {
/*setC is asynchronous (withoutFlushSync), so it continues the
code downwards and therefore from the DOM it
brings us the value without increment in 1*/
setC((c) => c + 1);
console.log(document.getElementById("myId").innerText); // old value from DOM
console.log(c); // However below log will still point to old value ***BECAUSE OF CLOSURE***
};
const inc2 = () => {
/*waits until the DOM is modified with the new state (in the first click
c = 1)*/
ReactDOM.flushSync(() => { // Wait
setC((c) => c + 1);
});
/* brings the c = 1 of the DOM because it waited until the DOM
was modified with the new state incremented by one. */
console.log(document.getElementById("myId").innerText); // new value from DOM
console.log(c); // However below log will still point to old value ***BECAUSE OF CLOSURE***
};
return (
<div className="App">
Count: <div id="myId">{c}</div>
<button onClick={inc1}>without flushSync</button>
<button onClick={inc2}>with flushSync</button>
</div>
);
}
问题未解决?试试以下方法:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.