react 渲染过程中set state的报错

6,387 阅读1分钟

报错信息:

Warning: Cannot update a component (`ConnectFunction`) while rendering a different component...

业务场景:

react hooks 写法,组件A嵌套组件B,在A组件中,获取完用户信息,从用户信息中提取某个数据,再填充到model state中,这个在使用dispatch来set state model时,发生了报错。下面是简单的代码示例:

const Layout: FC<PageProps> = ({loading, currentUser}) => {
  useEffect(() => {
    dispatch({
        type: 'user/fetchCurrent'
    });
  }, []);
  
  if ( currentUser && dispatch ) {
    //这里是出现问题的地方
    dispatch({
        type: 'user/setPermission',
        payload: currentUser.permission.find(item.id == pid),
    });
  }
  
  return <PageHeaderWrapper>{children}</PageHeaderWrapper>;
};

解决办法

从官网上查到了这样的报错信息:

It is supported to call setState during render, but only for the same component. If you call setState during a render on a different component, you will now see a warning:

Warning: Cannot update a component from inside the function body of a different component.

官网页面地址:pl.reactjs.org/blog/2020/0…

从上面的描述中了解到,支持在同一个组件渲染过程中去set state,但如果在不同的组件渲染过程中去set state时,就会报这个warning。

从业务的场景来说,在dispatch时,并无阻塞加载,此时chidren组件渲染,在渲染过程中,父组件又更新了state,这时父组件又要重新渲染,这与children的渲染流似乎是冲突了。虽然页面能正常显示,这个warning也是提示我们最好不要这样做。

所以解决办法是把set state搬到useEffect中去,监测currentUser有值时再去做这个 set state.

const Layout: FC<PageProps> = ({loading, currentUser}) => {
  useEffect(() => {
    dispatch({
        type: 'user/fetchCurrent'
    });
  }, []);
  
  useEffect(() => {
    if ( currentUser && dispatch ) {
        dispatch({
            type: 'user/setPermission',
            payload: currentUser.permission.find(item.id == pid),
        });
    }
  }, [currentUser]);
  
  return <PageHeaderWrapper>{children}</PageHeaderWrapper>;
};