You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 10:27:45