6

I'm currently trying to implement React Router inside my app, I wanted to use the last version (6.4) with a Layout on all pages, so I use createBrowserRouter with my Layout element and all children to make different routes, but actually I can't see any of them with my code.

I would like to get the layout on every page, with conditional rendering depending navigation, so I must put it inside the router.

I tried to follow the doc (https://reactrouter.com/en/main/routers/create-browser-router) , nest routes with children item :

Router component :

const router = createBrowserRouter([
    {
        element: <Layout />,
        children: [
            {
                path: '/',
                element: <Dashboard />,
            },
            {
                path: 'gestion_preferences',
                element: <ManagePreferences />,
            },
            {
                path: 'trame_preferences',
                element: <ManageTrames />,
            },
        ],
    },
])

Layout component :

const Layout = () => {

  return (
        <Container
            sx={{ height: '100%' }}
            maxWidth={false}
            disableGutters={true}
        >
            <Header  />
            <Box
                sx={{
                 height: "100%",
                  overflowY: "auto",
                  display: 'flex',
                  flexDirection: 'column',
                  justifyContent: 'center',
                  alignItems: 'center',
                  bgcolor: 'background.main',
                  zIndex:1,
                }}
            >
                <Outlet />
            </Box>
            <Footer />
        </Container>
  )
}

App component :

const router = createBrowserRouter(routesConfig)

const App = () => {
    return (
        <ThemeProvider theme={theme}>
                <CssBaseline />
                <UserProvider>
                    <Layout>
                        <RouterProvider router={router} />
                    </Layout>
                </UserProvider>
        </ThemeProvider>
    )
}


I don't want to repeeat the Element inside all my components by hand

Edit : I add others components working together, I also tried in my layout to put {children} instead of Outlet

Steve
  • 63
  • 1
  • 1
  • 5
  • Please share ***all*** relevant code you are working with as part of a complete [mcve]. Does this help answer your question? https://stackoverflow.com/a/69999387/8690857 – Drew Reese Nov 29 '22 at 16:46
  • Thanks for the answer, unfortunately this don't solve my problem, but I tried to provide more infos on the main post – Steve Nov 30 '22 at 09:13

1 Answers1

3

Issue

From what I can tell of your code examples the issue is that the Layout component is being rendered in two places. Once correctly as a layout route where the nested routes can render their element into the Outlet rendered by Layout, and again in the App component wrapping the RouterProvider component. The issue is that Layout doesn't consume and render any children prop, so the wrapped RouterProvider isn't rendered.

Layout

const Layout = () => { // <-- no children prop
  return (
    <Container
      sx={{ height: '100%' }}
      maxWidth={false}
      disableGutters={true}
    >
      <Header />
      <Box ....>
        <Outlet />
      </Box>
      <Footer />
    </Container>
  )
}

App

const router = createBrowserRouter(routesConfig);

const App = () => {
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <UserProvider>
        <Layout>
          <RouterProvider router={router} /> // <-- child of Layout
        </Layout>
      </UserProvider>
    </ThemeProvider>
  );
};

Solution

The BrowswerRouter data router is already rendering the Layout component, so it's completely unnecessary in the App component and should be removed.

App

const router = createBrowserRouter(routesConfig);

const App = () => {
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <UserProvider>
        <RouterProvider router={router} />
      </UserProvider>
    </ThemeProvider>
  );
};
Drew Reese
  • 165,259
  • 14
  • 153
  • 181