最近编写前端上传和下载的功能,碰到了这个问题。
antd里面的upload组件设置为受控组件,然后我的onchange函数是这样写的。
const handleUploadChange = (info: UploadChangeParam<UploadFile<any>>) => {
console.log('info', info)
dispatch(
setUploadProgressModalOptions({
...uploadProgressModalOptions,
open: true,
})
)
setCurrentUploadFileList(info.fileList)
if (
!info?.event &&
info.fileList.every((item) => {
return item.status == 'done'
})
) {
refreshCurentWorkDir()
setTimeout(() => {
dispatch(
setUploadProgressModalOptions({
...uploadProgressModalOptions,
open: false,
})
)
setCurrentUploadFileList([])
}, 2000)
}
}
同时我把currentUploadFileList里面的下载进度遍历渲染出来,结果发现文件下载到一半就卡住了。实际上文件是下载完成了,只是渲染进度的地方卡住了。
log输出的info里面,最后一次输出,并没有都达到done
一开始我是用redux来保存这个列表,所以进度是正常显示的(redux并没有react18的问题)。但是redux会给你一个报错,因为里面有函数和对象,不建议用redux保存,所以我就换成setState了,反正这个下载进度是不需要持久化的。
其实这是react18的特性带来的问题。因为react18会把相近的多次setState进行合并。
如果我们希望回到以前的效果每一次setState都会执行,可以用flushSync包裹,这样这次setState会立刻执行。
flushSync(() => setCurrentUploadFileList(info.fileList))
下面回顾一下react18的一些改动
- Automatic batching 也就是会将多次setState合并到一次渲染的功能。虽然提升了渲染性能,但是会影响到我们的一些代码,当我们希望调用setState 后立刻渲染,可以用flushSync包裹(注意:
flushSync
函数内部的多个setState
仍然为批量更新,这样可以精准控制哪些不需要的批量更新。)。还有就是 在 setTimeout和原生js事件中 中不会进行批处理 - 新的createRoot api
const container = document.getElementById("app");
// 旧 render API
//ReactDOM.render(<App tab="home" />, container);
// 新 createRoot API
const root = ReactDOM.createRoot(container);
root.render(<App tab="home" />);
// React 17
ReactDOM.unmountComponentAtNode(root);
// React 18
root.unmount();
-
Concurrent Mode 就是一种可中断渲染的设计架构。当一个更高优先级渲染到来时,通过放弃当前的渲染,立即执行更高优先级的渲染,换来视觉上更快的响应速度。
-
Strict Mode 会帮你对每个组件进行两次渲染,方便调试并发模式的bug,因为我不需要这个并发模式,所以现在都是注释掉
-
放弃ie11的支持
-
在
React 17
中,如果你需要返回一个空组件
,React只允许返回null
。如果你显式的返回了undefined
,控制台则会在运行时抛出一个错误。在
React 18
中,不再检查因返回undefined
而导致崩溃。既能返回null
,也能返回undefined
(但是React 18
的dts
文件还是会检查,只允许返回null
,你可以忽略这个类型错误)。
网友评论