简体   繁体   中英

Component inside component in React Router

I'm trying to make use of Mantine's App shell ( https://mantine.dev/core/app-shell/ ) in React Router to have it enabled on only specific routes.

How is it possible to implement this.

Usually, to display a component I would to the following, for example:

<Route element={<SidebarLayout {...{ inactive, setInactive }} />}>
                <Route path="/" element={<Main />} />

But in this case, I got way more code (based on the example in the docs) - I'm planning to add a component inside this <AppShell> Component (please look all the way down):

<AppShell
      styles={{
        main: {
          background:
            theme.colorScheme === "dark"
              ? theme.colors.dark[8]
              : theme.colors.gray[0],
        },
      }}
      navbarOffsetBreakpoint="sm"
      asideOffsetBreakpoint="sm"
      navbar={
        <Navbar
          p="md"
          hiddenBreakpoint="sm"
          hidden={!opened}
          width={{ sm: 200, lg: 300 }}
        >
          <Text>Application navbar</Text>
        </Navbar>
      }
      aside={
        <MediaQuery smallerThan="sm" styles={{ display: "none" }}>
          <Aside p="md" hiddenBreakpoint="sm" width={{ sm: 200, lg: 300 }}>
            <Text>Application sidebar</Text>
          </Aside>
        </MediaQuery>
      }
      footer={
        <Footer height={60} p="md">
          Application footer
        </Footer>
      }
      header={
        <Header height={70} p="md">
          <div
            style={{ display: "flex", alignItems: "center", height: "100%" }}
          >
            <MediaQuery largerThan="sm" styles={{ display: "none" }}>
              <Burger
                opened={opened}
                onClick={() => setOpened((o) => !o)}
                size="sm"
                color={theme.colors.gray[6]}
                mr="xl"
              />
            </MediaQuery>

            <Text>Application header</Text>
          </div>
        </Header>
      }
    >
      <Text>Resize app to see responsive navbar in action</Text> <-- PLANNING TO ADD COMPONENT HERE BASED ON ROUTE
    </AppShell>

How can I integrate this whole thing in React Router?

As the "SidebarLayout" name implies, you are asking how to implement what is called a layout route . Layout routes generally render some common logic and UI elements/components, and an Outlet component for nested routes to render their content into. You generally render the Outlet component where you'd normally render the children prop.

Example:

Render an Outlet below the Text component.

<AppShell
  ...
>
  <Text>Resize app to see responsive navbar in action</Text>
  <Outlet /> // <-- render Outlet here for nested routes
</AppShell>

Usage:

<Routes>
  <Route element={<SidebarLayout {...{ inactive, setInactive }} />}>
    <Route path="/" element={<Main />} />
    ... other routes with SidebarLayout ...
  </Route>

  ... other routes w/o SidebarLayout ...
</Routes>

This can be done in 2 ways:

Loading AppShell in a wrapper function:

By loading the AppShell component inside a wrapper function, you can wrap your sub-components by passing them based on the route path.

  1. You need to create a separate wrapper component, let's call it withAppShell component, now you can load it as follows:
export const withAppShell = (ChildComponent) => 
    ( 
        <AppShell ... // App Shell code start
        <ChildComponent /> // the part where you wish to load your child component
        </AppShell> // App Shell code end
    )
  1. To use it, first import, then:
withAppShell(ChildComponent);

Loading AppShell in a wrapper component:

Feels similar to the first one, but is not-

  1. Create the component:
export const AppShellWrapper = ({children}) => 
    (
        <AppShell ... //start
        {children}
        </AppShell> //end
    )
  1. Using it, first import, then:
<AppShellWrapper>
   <ChildComponent />
</AppShellWrapper>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM