使用useMediaQuery导致TextField卡顿?如何优化响应式条件渲染逻辑
卡顿根因
你遇到的输入卡顿确实和条件渲染有关:
- 当屏幕尺寸跨
md断点时,MyForm会被完整卸载/挂载,复杂表单的挂载卸载开销较高 - 若
useMediaQuery的返回值变化、或父组件存在其他状态更新,都会触发MyForm的全量重渲染,输入时每输入一个字符就会触发一次重渲染,进而出现卡顿
优化方案
方案1:使用CSS显隐替代条件渲染(最推荐)
这是解决重渲染卡顿最直接的方式,避免表单组件随断点变化频繁挂载/卸载:
// 桌面端表单:md及以上显示,md以下隐藏 <MyForm sx={{ display: { xs: 'none', md: 'block' } }} /> // 移动端触发按钮:md以下显示,md及以上隐藏 <Button onClick={openFormModal} sx={{ display: { xs: 'inline-flex', md: 'none' } }} /> // 模态框内表单正常实现,仅在模态框打开时渲染即可
如果父组件存在其他重渲染逻辑,可使用React.memo包裹MyForm组件,仅当表单props变化时才触发重渲染,进一步降低性能开销。
方案2:隔离媒体查询逻辑与表单渲染
如果需要保留条件渲染逻辑,可将媒体查询判断、按钮、表单抽离为独立的子组件,避免父组件其他状态更新触发这部分的不必要重渲染:
// 抽离后的独立组件 const FormEntry = React.memo(({ openFormModal }) => { const isMobile = useMediaQuery((theme) => theme.breakpoints.down("md")); return isMobile ? ( <Button onClick={openFormModal} /> ) : ( <MyForm /> ) })
父组件直接调用FormEntry即可,父组件其他状态更新不会触发FormEntry的重渲染。
方案3:独立管理表单状态
如果表单状态声明在父组件中,输入时状态更新会触发父组件整体重渲染进而导致表单卡顿,可将表单状态收敛到MyForm组件内部,或使用状态管理工具单独管理表单状态,切断表单状态更新与父组件渲染的关联。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

