How to toggle RTL/LTR at runtime in React + Material UI properly?

Viewed 884

I read that using Material ui you need to follow these steps to support RTL.
I have a select input to toggle between languages (this will update the app direction)

This is my root component (Im using jss-rtl to control Material UI components direction):

const jss = create({ plugins: [...jssPreset().plugins, rtl()] })

function withRoot(Component) {
  function WithRoot(props) {
    return (
      <StylesProvider jss={jss}>
        <MuiThemeProvider theme={createMuiTheme({ direction: i18next.dir() })}>
          <Component {...props} />
        </MuiThemeProvider>
      </StylesProvider>
    )
  }

  return WithRoot
}

function App() {
  const [t, i18n] = useTranslation()
  const theme = useTheme()

  document.body.dir = i18n.dir()

  const changeLanguage = (lng) => {
    i18n.changeLanguage(lng)
    document.body.dir = i18n.dir()
    theme.direction = i18n.dir()
  }

  return (
    <div>
      <CssBaseline/>
      <SomeComponent/>
      <button onClick={() => changeLanguage('en')}>en</button>
      <button onClick={() => changeLanguage('he')}>he</button>
    </div>
  )
}

export default withRoot(App)

This works and my content is now in RTL layout. But when i toggle back with the "en" button, the body itself is now LTR (which is right) but the actual material ui components are still RTL (because of const jss = create({ plugins: [...jssPreset().plugins, rtl()] })).

Is there a way to toggle this rtl() plugin at runtime? or other proper way to toggle between RTL/LTR in material UI?

1 Answers

Bellow solution fixes for me!

_app.tsx

const MyApp = ({ Component, pageProps }) => {
  useEffect(() => {
    document.body.dir = i18n.dir();
  }, [i18n.dir()]);

....

return(
    <StylesProvider jss={jss}>
        <MuiThemeProvider theme={{ ...theme, direction: i18n.dir() }}>
        <ToolBar 
         onChangeLanguageClick={() => {
                        props.setLanguage(props.language === 'ar' ? 'en' : 'ar');
                        i18n.changeLanguage(props.language === 'en' ? 'ar' : 
                     'en');
                        theme.direction = props.language === 'ar' ? 'ltr' : 'rtl';
                      }}
                 />
            <Component {...pageProps} />
        </MuiThemeProvider>
      </StylesProvider>
)

}

theme.js file

const theme = createMuiTheme({
  typography: {
    fontFamily: ['Roboto'].join(','),
    fontSize: 14,
  },
  palette: {},
});

export default theme;

Related