5

I'm new to React and React Router. I'm using React Router v4 and following a tutorial based on previous versions - but I made it work (using some stuff found on SO and some stuff on the react router v4 docs).

There is one thing though that is bothering me.

I have a url http://localhost:3000/#/bugs, which basically loads a list of all my bugs. But I also have possible urls like http://localhost:3000/#/bugs?priority=low&status=open which loads a specific set of urls.

The urls themselves work and do the job as expected.

The werid thing is that whenever I type http://localhost:3000/#/bugs?priority=low&status=open (or any params), the component do their jobs but the URL address bar shows http://localhost:3000/#/bugs (although the rendering shows everything related to priority and status shown).

Somehow, the URL location bar is changed but I don't understand why.

Here is my App.js

import React from 'react';
import ReactDOM from 'react-dom';
import {BugList} from './BugList';
import {Redirect} from 'react-router';
import {HashRouter as Router, Route} from 'react-router-dom';



const NoMatch = React.createClass({
    render : function (){
        return(
            <h2>This path does not exist</h2>
        );
    }
});


ReactDOM.render(
    (
        <Router>
            <div>
                <Route path='/bugs' component={BugList}/>
                <Route path='/bugs/priority/:priority' component={BugList}/>    
                <Redirect from='/' to="/bugs" />
                <Route path="*" component={NoMatch} />
            </div>
        </Router>
    ),
    document.getElementById('main')
);

Thanks in advance.

EDIT 12th of April. Despite of the precious help of someone below, this is still not solved. I tried using Switch inside a Router but it doesn't work at all (nothing is shown). So the problem is still happening, and this is the current state of my App.js, using react-15.5.3, react-dom-15.5.3, react-router-4.0.0 and react-router-dom-4.0.0....

import React from 'react';
import ReactDOM from 'react-dom';
import {BugList} from './BugList';
import BugEdit from './BugEdit';
import {Redirect} from 'react-router';
import {HashRouter as Router, Route} from 'react-router-dom';

const NoMatch = React.createClass({
    render : function (){
        return(
            <h2>This path does not exist</h2>
        );
    }
});

ReactDOM.render(
    (
        <Router>
            <div>
                <Redirect from='/' to="/bugs" />
                <Route path='/bugs' component={BugList}/>
                <Route path='/bug/:id' component={BugEdit}/>
                <Route path="*" component={NoMatch} />
            </div>
        </Router>
    ),
    document.getElementById('main')
);

3 Answers 3

3

The problem is that even if you enter the URL with query this URL matches Redirect path (since it's just / any URL matches this pattern) so the redirection to /bugs occurs. You have to use Switch (remember to import it) to render only the first <Route> or <Redirect> that matches the URL:

<Router>
     <Switch>
        <Route path='/bugs' component={BugList}/>
        <Redirect from='/' to="/bugs" />
        ...
   </Switch>
</Router>

The problem occured only on page load and not on re-entering the URL because your routing is based on hashes and the browser doesn't reload page when only hash part changes.
Please note that Redirect component in React-Router v4 performs redirection only when it's rendered - it doesn't set up permanent redirection rule so in your case redirection works only on page load. If you'd like your app to always redirect given URL you'd have to define Route for URL you'd like to redirect from and render Redirect:

<Route path='/oldUrl' render={() => (
    <Redirect to="newUrl" />
)}/>

Furthermore, React-Router v4 is quite different from v3 so I don't recommend using v3 tutorials - it doesn't make sense.

Sign up to request clarification or add additional context in comments.

7 Comments

Cheers. Now that you say it, it's pretty obvious but you just unblocked me! Thanks a lot!
Actually I got it wrong. It still has the same behavior. I load localhost:3000/#/bugs?priority=low&status=open and it ignores this and goes to localhost:3000/#/bugs automatically.
Ok, so next thing is that your URL doesn't match route path pattern because you pass priority as query - your URL should be like this: localhost:3000/#/bugs/priority/low?status=open. Your Route path expects priority as path segment not as query
I made some changes to my routing because I've decided to use query parameters (as per my example URL), so now it's <Redirect from='/' to="/bugs" /> <Route path='/bugs' component={BugList}/> <Route path="*" component={NoMatch} /> But it still fails. The weird thing is that it only fails on the first load of the React components. I mean if I open a new tab and put the url localhost:3000/#/bugs?priority=low&status=open , it redirects me to localhost:3000/#/bugs. But then if in the same tab I re-enter localhost:3000/#/bugs?priority=high&status=closed (for example), the URL stays
Thanks! Still not working, I get this error :Warning: Failed context type: The context router is marked as required in Switch, but its value is undefined. in Switch`
|
1

Building on what Bartek said: if you use Switch, it will go directional from top to bottom and render the first hit, since you moved your redirect to the first position it will always hit that first and then not go to the other routes. Which is why your Switch should look like this imho (untested):

<Router>
    <Switch>
        <Route path='/bugs' component={BugList}/>
        <Route path='/bug/:id' component={BugEdit}/>
        <Redirect from='/' to="/bugs" />
        <Route path="*" component={NoMatch} />
    </Switch>
</Router>

1 Comment

Cheers, I'll try this!
0

I know its 04/2020, but this will fix your issue.

    <Switch>
        <Route path='/bug/:id' component={BugEdit}/>
        <Route path='/bugs' component={BugList}/>
        <Redirect from='/' to="/bugs" />
        <Route path="*" component={NoMatch} />
    </Switch>
</Router>```

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.