如何让Chakra UI模态框内容仅在打开时渲染一次?
解决Chakra UI模态框内部组件重复挂载的问题
原因分析
- React 18严格模式(开发环境特性):React 18的StrictMode会在开发环境下触发组件两次挂载(包括
useEffect执行两次),目的是检测潜在的副作用问题,生产环境不会出现该行为。你之前使用Material UI未遇到此问题,可能是当时项目未开启StrictMode,或是Material UI组件内部做了兼容处理。 - Chakra UI Modal的Portal机制:Chakra的Modal默认通过Portal将内容挂载到DOM根节点之外,该机制在StrictMode下会放大重复挂载的表现,但核心原因仍是StrictMode的特性。
解决方案
1. 验证StrictMode影响
在项目入口文件(如index.tsx/index.jsx)中,暂时移除<StrictMode>的包裹,测试模态框打开时组件是否仍会重复挂载。若问题消失,说明是StrictMode的开发环境特性,生产环境不会出现重复请求。
2. 确保数据请求不重复执行
无论是否是StrictMode导致,都要避免重复发送请求:
- 使用React Query或SWR等数据缓存库:这类库会自动缓存请求结果,相同请求仅发送一次,后续直接读取缓存。
- 手动实现请求控制:在时段列表组件中添加状态标记,避免重复触发请求。示例代码:
const ReservationList = () => { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(false); useEffect(() => { if (isLoading || data) return; // 已加载或正在加载时不再发起请求 setIsLoading(true); fetch('/api/reservations') .then(res => res.json()) .then(resData => { setData(resData); setIsLoading(false); }) .catch(err => { console.error(err); setIsLoading(false); }); }, [data, isLoading]); // 渲染逻辑 return ( <div>{isLoading ? '加载中...' : JSON.stringify(data)}</div> ); };
3. Chakra UI Modal配置调整
若确认不是StrictMode问题,可尝试以下调整:
- 禁用Portal:给Modal添加
disablePortal={true}属性,让Modal内容直接挂载在当前组件树中,避免Portal带来的额外渲染。 - 升级Chakra UI版本:旧版本Chakra可能存在重复挂载的bug,升级到最新稳定版可能解决问题。
总结
开发环境下的StrictMode触发两次挂载是React 18的正常行为,重点是确保数据请求不会重复执行。若生产环境也出现该问题,再排查Chakra UI的配置或版本问题,或尝试禁用Portal等调整。
内容的提问来源于stack exchange,提问作者cheerful_weasel
相关产品推荐
相关产品推荐

