Ben*_*ams 5 javascript typescript reactjs react-hooks
TL;DR React 有时呈现加载状态,有时不呈现,UI 没有变化。这可能是由于批量更新造成的。
我想知道下面的问题是否是由于批量更新造成的。如果答案是“是”,我想知道是否有首选的方式来选择退出 React 中的批量更新以获得确定性的渲染行为。如果您想跳过设置,请转到“实验”。
设置
这是设置,一个需要很长时间渲染的图表。这么长时间渲染被阻塞。这里有三种不同的方式来渲染图表:
setTimeout选项 2 和 3 都有一个useState检查它们是否已安装的小工具。我这样做是为了有条件地显示“正在加载”状态:
function ChartWithMountHack({ data }: { data: Data }) {
// initially not mounted
const [isMounted, setIsMounted] = useState<boolean>(false);
useEffect(() => {
// "Now I've been mounted!"
setIsMounted(true);
}, []);
return !isMounted ? <p>Loading</p> : <Chart data={data} />;
}
Run Code Online (Sandbox Code Playgroud)
我这样做是因为我想显示“正在加载”状态而不是阻塞渲染,因此例如页面切换或三元渲染(例如hasData ? <p>No data</p> : <Chart />)会立即显示,而不是阻塞。(如果有更好的方法,请告诉我!)
实验
现在,每个按钮将呈现三个选项/图表之一。同样,第二个和第三个图表有一个小技巧来检查它们是否已安装。
尝试快速来回单击第一个按钮和第二个按钮。您会看到有时“带挂载的图表”会(“正确地”)呈现“正在加载”状态,但有时它只是不呈现“正在加载”-而是阻止呈现,直到图表完成呈现(跳过“加载”状态)。
我认为这是由于渲染周期以及您是否在批处理的一个周期中获得两次更新。(第一:isMounted === false- >第二:isMounted === true)
我真的不知道如何重现这个,因此标题中的“不确定性”。有时您还必须单击“重新生成数据”,然后来回单击。
交叉检查
选项 3(“带有超时挂载的图表”)总是给我“正在加载”状态,这正是我想要的。与选项 2 的唯一区别是setTimeout在设置为 true的useEffectwhere 中使用 a isMounted。setTimeout此处用于突破更新批处理。
是否有更好的方法来选择退出批处理,因此isMounted将始终以其初始值 ( false) 进行渲染?setTimeout在这里使用感觉就像一个黑客。
React 具有并发功能来处理此类事情,例如 React Suspense 标签,或者您可以使用 Rxjs 等订阅库,其订阅应在 componentDidMount 和 componentWillUnmount 中完成以取消订阅数据。
那么 isMounted 只是解决未决问题的方法,可能来自您正在使用的库,或者有时只是您的捆绑器/构建工具发挥了一点作用。
最后,为了避免不必要的重新渲染,您可以使用 React.Memo 对组件进行 React 记忆。
请阅读更多相关内容。
| 归档时间: |
|
| 查看次数: |
89 次 |
| 最近记录: |