Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support nested Switches #467

Open
mnieber opened this issue Jul 10, 2024 · 6 comments
Open

Support nested Switches #467

mnieber opened this issue Jul 10, 2024 · 6 comments

Comments

@mnieber
Copy link

mnieber commented Jul 10, 2024

Hi, I've read the docs to see if nested Switches are supported (a longstanding wish), and I think they are not, so I wanted to make a feature proposal.

The idea is that a switch picks the first matching route or switch. A switch matches if one of its routes (or switches) matches. It's basically the Composite pattern.

The use-case is this one:

<Switch>
    <Route path="blue/one"/>
    <Route path="red/one"/>
    <Route path="bread/one"/>
    <Route path="apple/one"/>
</Switch>

If I want to create separate route groups for "color" or "food" then it would be great if I can refactor this to

// Switch that renders either ColorsSwitch or FoodsSwitch.
// This approach can be used to clean up switches with many routes.
// It can also be used to reuse switches in different locations.
<Switch>
    <ColorsSwitch/>
    <FoodsSwitch/>
</Switch>

const ColorsSwitch = () => {
    return (
        <Switch>
            <Route path="blue/one"/>
            <Route path="red/one"/>
        </Switch>
    )
}

const FoodsSwitch = () => {
    return (
        <Switch>
            <Route path="bread/one"/>
            <Route path="apple/one"/>
        </Switch>
    )
}
@schmitch
Copy link

schmitch commented Jul 22, 2024

yeah I had the same problem that switch does not work well with nested routes like:

function ComponentTreeBRouter() {
return       <><Route path="/">
        <Redirect to="/list"/>
      </Route>

      <Route path="/list">
        <ComponentC/>
      </Route>
      <Route path="/overview/:id">
        {params => <ComponentD/>}
      </Route></>;
}
<Router base="...">
           <Route path="/component-tree-a" nest>
          <>
            <Route path="/">
              <ComponentA/>
            </Route>
            <Route path="/config">
              <ComponentB/>
            </Route>
          </>
        </Route>

        <Route path="/component-tree-b" nest>
          <ComponentTreeBRouter/>
        </Route>

        <Route><Error404RouteComponent/></Route>
      </Switch>
</Router>

actually I created a NestedRouter which I wrapped inside the nested routes, like:

function EvRouter(props: { children: ReactNode }) {
  return (<Switch>
    {props.children}
    <Route><Error404RouteComponent/></Route>
  </Switch>);
}

switch than looks like:

<Router base="...">
           <Route path="/component-tree-a" nest>
          <EvRouter>
            <Route path="/">
              <ComponentA/>
            </Route>
            <Route path="/config">
              <ComponentB/>
            </Route>
          </EvRouter>
        </Route>

        <Route path="/component-tree-b" nest>
          <ComponentTreeBRouter/> <!-- also has EvRouter inside as the first component -->
        </Route>

        <Route><Error404RouteComponent/></Route>
      </Switch>
</Router

I would prefer if something like:

<Switch>
      <ComponentTreeARouter />
      <ComponentTreeBRouter />
      <Route><Error404RouteComponent/></Route>
</Switch>

but looks like that might be hard to support...

@mnieber
Copy link
Author

mnieber commented Jul 22, 2024

@schmitch It's a bit hard to follow what your problem with nested routes is. Can you give an example of the thing that doesn't work for you, but only using Switch and Route? (and no custom components). Or is it (exactly) the same problem as what I posted?

@schmitch
Copy link

@mnieber actually the custom components is the problem.

we prefer them to make nested routes since we have tons of routes

@haggen
Copy link

haggen commented Jul 27, 2024

I need something like this so that some routes share a context provider.

// App.jsx
<Switch>
  <Route path="/a" component={A} nest />
  <Route path="/b" component={B} />
</Switch>

// A.jsx
<Provider>
  <Switch>
    <Route path="/1" component={A1} />
    <Route path="/2" component={A2} />
  </Switch>
</Provider>
@mnieber
Copy link
Author

mnieber commented Jul 28, 2024

@haggen It looks like your example would already work with the current Switch. Doesn't it work?

@haggen
Copy link

haggen commented Jul 29, 2024

@mnieber Oh indeed it does! Reading the docs I was under the impression that Routes needed to be directly nested. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants