模态框内组件重复渲染两次的原因及修复方案咨询
为什么会出现两次渲染/API调用?
主要有两个核心原因:
React 18 严格模式(Strict Mode)的刻意重复渲染
在开发环境下,React 18的Strict Mode会对组件进行两次挂载/渲染(生产环境不会有这个行为),目的是帮你检测组件中可能存在的副作用问题。你的UsersFormPermissionsGroupPermissions组件里的useEffect没有依赖数组,所以每次渲染都会执行,加上Strict Mode的重复渲染,就触发了两次API调用。useEffect缺少依赖数组
你的useEffect没有指定依赖项,这意味着它会在组件的每次渲染完成后都执行。哪怕没有Strict Mode,只要组件因为props/state变化重新渲染,这个useEffect都会再次触发API请求,这本身就是不符合预期的写法。
另外,父组件的条件渲染写法虽然不会直接导致两次渲染,但可以做些优化,避免不必要的组件销毁重建。
修复步骤
1. 给useEffect添加正确的依赖数组
修改UsersFormPermissionsGroupPermissions里的useEffect,把它依赖的变量idGroupCompany和dispatch加入依赖数组,这样只有当这些变量变化时,才会重新触发API请求:
useEffect(() => { console.log('fetching permissions') dispatch(groupPermissionsActions.getPermissionsGroupById(idGroupCompany)) }, [idGroupCompany, dispatch]) // 这里添加依赖项
如果dispatch是从Redux的useDispatch获取的,它本身是稳定的,可以安全加入依赖数组。
2. 优化组件传递,避免不必要的重渲染
把UsersFormPermissionsGroupPermissions用React.memo包裹,这样当它的props没有变化时,不会重复渲染:
import { memo } from 'react'; const UsersFormPermissionsGroupPermissions = memo(() => { // 你的组件代码 })
同时,父组件传递FormComponent的时候,不要在渲染时创建新的组件引用(不过你现在是直接传组件,没问题,但如果是传渲染函数的话要注意)。
3. (可选)理解Strict Mode的行为
如果你只是在开发环境看到两次调用,生产环境不会有这个问题,这是React的正常检测机制。如果想暂时关闭Strict Mode,可以在index.js里去掉<StrictMode>标签,但不建议这么做,因为它能帮你提前发现潜在的bug。
4. 优化父组件的条件渲染写法
父组件里的条件渲染可以简化,不需要写三元表达式的空片段,直接写成:
{openFullScreenModal && ( <ModalFullScreen FormComponent={UsersFormPermissionsGroupPermissions} title="Permissões do grupo" onCloseModal={setOpenFullScreenModal} open={openFullScreenModal} /> )}
这样代码更简洁,而且逻辑上和原来一致。
验证修复效果
修改后,在开发环境下,Strict Mode仍然会触发两次组件渲染,但因为useEffect有了依赖数组,只有当idGroupCompany变化时才会执行API请求;如果idGroupCompany没有变化,第二次渲染时useEffect不会重复执行,从而避免了两次API调用。生产环境下则只会执行一次。
内容的提问来源于stack exchange,提问作者匿名用户

