Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why getPopupContainer doesn't work correctly in my react app?

I'm getting this warning:

Warning: [antd: Modal] Static function can not consume context like dynamic theme. Please use 'App' component instead.

Then, the Modal.confirm() doesn't show correctly because it renders outside of the dependency tree and doesn't inherit the styles.

I'm using react 18.2.0 and antd 5.4.6.

Here I leave the code

main.tsx

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <Suspense fallback={<Loader />}>
     <ThemeWrapper>
         <Outlet />
      </ThemeCoWrapper>
  </Suspense>
);
const ThemeWrapper: React.FC<ThemeProps> = ({ children }) => {
  const [theme, setTheme] = useState<any>(defaultTheme);

  const modalContainerRef = useRef<HTMLDivElement>(null);

  return (
    <ConfigProvider
      theme={theme}
      getPopupContainer={() => modalContainerRef.current as HTMLElement}
    >
      <div ref={modalContainerRef}>{children}</div>
    </ConfigProvider>
  );
};

export default ThemeWrapper;

Example of function in which I use the Modal.confirm() inside the wrapper

const onLogout = () => {
    Modal.confirm({
      title: (
        <b>
          {intl.formatMessage({
            id: 'labelCloseSession',
          })}
        </b>
      ),
      content: intl.formatMessage({
        id: 'labelLogoutConfirm',
      }),
      centered: true,
      onOk: async () => {
        try {
          await loginService.logout();
          removeUserSession();
          globalContext.dispatch({
            type: GlobalStateActionType.LOGOUT,
          });
          navigate('/login');
        } catch (error) {}
      },
    });
  };

I tried to use document.getElemetById instead of useRef but it didn't work.

like image 867
jesusrlm Avatar asked Sep 11 '25 03:09

jesusrlm


1 Answers

Because static function in React 18 concurrent mode will not well support. In v5, Antd recommends to use hooks for the static replacement (read here). So, you will need to set up your project like what they stated here: https://ant.design/components/app#basic-usage

In your case, try:

  • For the ThemeWrapper component
  • import { App } from 'antd';
  • And then, wrap the <div> element in <App></App> like:
    <ConfigProvider
         theme={theme}
         getPopupContainer={() => modalContainerRef.current as HTMLElement}
    >
         <App>
             <div ref={modalContainerRef}>{children}</div>
         </App>
    </ConfigProvider>
    

Here, I provide the codesandbox example: https://codesandbox.io/s/text-and-link-component-antd-5-0-2-forked-9svf8v?file=/demo.tsx They recommend encapsulating App at the top level in the application

After that, you will need to use modal.confirm({}) from App.useApp(); instead of the old Modal.confirm() in your onLogout function.

like image 111
Khairani F Avatar answered Sep 12 '25 18:09

Khairani F