React Router v4 global no match to nested route childs
Asked Answered
A

2

3

How can I redirect the user to a NoMatch component when I have nested routes in React Router V4?

Here is my code:

import React from 'react';
import ReactDOM from 'react-dom';
import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin();

import {
    BrowserRouter as Router,
    Route,
    Switch
}
from 'react-router-dom';
import Website from './website/Website';

const Register = ({ match}) => {
    return (
        <div>
            <Route exact path={match.url} render={() => {return <h1>Register</h1>} } />
            <Route path={`${match.url}/detail`} render={()=>{return <h1>Register Detail</h1>}} />
        </div>
    )
}

const App = () => (
    <Router>
        <Switch>
                <Route exact path="/" render={() =>  {return <h1>Home</h1> }} />
                <Route path="/register" component={Register} />
                <Route component={() => {return <h1>Not found!</h1>}} />
        </Switch>
    </Router>
);

ReactDOM.render(
    <App/>, document.getElementById('root'));

As You can see, there is a NoMatch route below Register but I don't want to use the same Route mapping on my child component Register. In this way, if I go to /register/unregisteredmatch the page just show blank because do not enter in NoMatch Route.

How can I map a global NoMatch without specify that on my child route? I don't want to pass this responsability to the child components.

Thanks.

Actinomycete answered 8/4, 2017 at 1:8 Comment(2)
you will need to create HoC, register will always render no matter if it has a matched child route inside or none. so you will need to create a handler for thatAlterant
@ReiDien If I understood, what I need to make is create an "abstract" component encapsuling the NoMatch handler... Am I right? Thank YouActinomycete
D
0

I have the same problem with Switch since the following will always render my NoMatch component if I do not go to /a

<Router history={history}>
  <Switch>
    <Route path='/a' component={A} />
    <Switch>
      <Route path='/b' component={B} />
      <Route path='/b/:id' component={C} />
    </Switch>
    <Route path="*" component={NoMatch}/>
  </Switch>
</Router>

However, it will work, as expected, if you move your NoMatch inside the nested Switch like this:

<Router history={history}>
  <Switch>
    <Route path='/a' component={A} />
    <Switch>
      <Route path='/b' component={B} />
      <Route path='/b/:id' component={C} />
      <Route path="*" component={NoMatch}/>  
    </Switch>
  </Switch>
</Router>

Even if this is a 'solution' to the problem it is not what you want since the second Switch is in a different file like the first Route is as well.

So as the application grows and more routes come into play in different files you never know where you need to put the NoMatch route for it to work as expected.

Did you find any other solution to this problem?

Diazine answered 7/5, 2017 at 12:2 Comment(2)
Hi! I think that the best approach to this tois use a High Order Component to handle the not found match as @ReiDien explained in the comment above. I didn't tried yet.Actinomycete
I found that nested Switch is not supported. So, having routes configured in different files you should not return a Switch from those. What I did was return an array of routes holding the /b and /b/:id routes.Diazine
C
-1

What you could do is define all possibly allowed routes in your root App. Therefore, adapt your App component using optional pattern as follows:

const App = () => (
    <Router>
        <Switch>
                <Route exact path="/" render={() =>  {return <h1>Home</h1> }} />
                <Route path="/register/(detail)?" exact component={Register} />
                <Route component={() => {return <h1>Not found!</h1>}} />
        </Switch>
    </Router>
);
Clausen answered 8/4, 2017 at 23:25 Comment(1)
Thank you @Javaguru! I'm trying to decouple my components without specify in a main file. Just for dynamic import purposes and because that I dont want to map my routes in a main file. I know that I can create a route file according the imports but I searching a way to do that on my modules.Actinomycete

© 2022 - 2024 — McMap. All rights reserved.