React router changes url but not view

Shubham Khatri

You need to specify the attribute exact for your indexRoute, otherwise for even /details route it will still match with / . Also try to import Route from react-router-dom

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route } from 'react-router-dom';
import Users from "./components/Users";

import Details from "./components/Details";

ReactDOM.render((
  <BrowserRouter>
    <div>
        <Route exact path="/" component={Users} />
        <Route path="/details" component={Details} />
    </div>
  </BrowserRouter>
), document.getElementById('app'))

UPDATE:

Another thing that you need to do is to attach your component Users with withRouter. You need to make use of withRouter only when your component is not receiving the Router props,

This may happen in cases when your component is a nested child of a component rendered by the Router or you haven't passed the Router props to it or when the component is not linked to the Router at all and is rendered as a separate component from the Routes.

In Users.js add

import {withRouter} from 'react-router';

.........
export default withRouter(Users)

DOCS

You just have to wrap the components inside withRouter.

< Route exact path="/mypath" component={withRouter(MyComponent)} />

Here is a sample App.js file:

...
import { BrowserRouter as Router, Route, Switch, withRouter } from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";

class App extends Component {
  render() {
    return (
      <Router>
        <Switch>
          <Route exact path="/" component={withRouter(Home)} />
          <Route exact path="/profile" component={withRouter(Profile)} />
        </Switch>
      </Router>
    );
  }
}

export default App;

OR

You can also maybe wrap the component in withRouter before exporting, but then you have to ensure a few other things.

export default withRouter(Profile)

When using Redux and I had similar issues where the url was updating in the address bar but the app was not loading the respective component. I was able to solve by adding withRouter to the export:

import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'

export default withRouter(connect(mapStateToProps)(MyComponentName))

You need to add exact to the index route and rather than enclosing those Route components by div, use Switch from react-router-dom to switch between the routes.

import React from "react";
import ReactDOM from "react-dom";
import { Route, Switch } from 'react-router-dom';
import Users from "./components/Users";

import Details from "./components/Details";

ReactDOM.render((
  <div>
    <Switch>
        <Route path="/" component={Users} exact/>
        <Route path="/details" component={Details} />
    </Switch>
  </div>
), document.getElementById('app'))

You should check this out: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md

Therefore it's definitely not Users or Details, because they are directly rendered by <Route>, and the location will get passed to props.

I am wondering, why do you need the <div> between <BrowserRouter> and <Route>? Remove that and let me know if it works.

I had similar issue with React Router version 4:

By clicking <Link /> component, URL would change but views wouldn't.

One of views was using PureComponent rather than Component (imported from react) and that was the cause.

By replacing all route rendered components that were using PureComponent to Component, my issue was resolved.

(Resolution source: https://github.com/ReactTraining/react-router/issues/4975#issuecomment-355393785)

I met trouble too.

https://github.com/chengjianhua/templated-operating-system

And I have tried the solutions metioned by Shubham Khatri, but It doesn't work.


I solved this problem, maybe can help you.

https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md

According the above guide document, when you use PureComponent or use with state management tools like redux, mobx ... It may block the update of your route. Check your route component, ensure you did't block the rerender od your component.

Try this,

import React from "react";

import ReactDOM from "react-dom";
import Users from "./components/Users";
import { Router, Route } from "react-router";


import Details from "./components/Details";

ReactDOM.render((
  <Router>
        <Route path="/" component={Wrapper} >
            <IndexRoute component={Users} />
            <Route path="/details" component={Details} />
        </Route>
  </Router>
), document.getElementById('app'))

Hmm there no any SWITCH to actually switch views.

this is how i use router to switch from landin page to main site

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


//App.jsx
render()
{
    return <div>
        <Switch>
            <Route exact path='/' component={Lander}/>
            <Route path='/vadatajs' component={Vadatajs}/>
        </Switch>
    </div>
}

https://jsfiddle.net/Martins_Abilevs/4jko7arp/11/

ups i found you use different router ..sorry then maybe this fiddle be for you useful

https://fiddle.jshell.net/terda12/mana88Lm/

maybe key of solution is hiden in line for main render function ..

Router.run(routes, function(Handler) {
    React.render(<Handler />, document.getElementById('container'));
});

I was facing similar issue I resolve to like this please have a look I hope it's working.

You need to use componentWillReceiveProps function in your component.

clicked a link first time by calling url www.example.com/content1/ componentDidMount() is run.

Now when you click another link say www.example.com/content2/ same component is called but this time prop changes and you can access this new prop under componentWillReceiveProps(nextProps) which you can use to call API Or make state blank and get new data.

componentWillReceiveProps(nextProps){
     //call your API and update state with new props
}

I had a similar issue with a conditional Layout:

class LayoutSwitcher extends Component {
  render () {
    const isLoggedIn = this.props.isLoggedIn
    return (
      <React.Fragment>
        { isLoggedIn
          ? <MainLayout {...this.props} />
          : <Login />
        }
      </React.Fragment>
    )
  }
}

and rewrote the conditions like so:

  render () {
    const isLoggedIn = this.props.isLoggedIn
    if (isLoggedIn) {
      return <MainLayout {...this.props} />
    }
    return <Login />
  }

This solved it. In my case, it seems that the context was lost.

I had a similar issue but with different structure. I've added one Router that will handle all routes, I've used Switch component to switch views. But actually, it didn't. Only URL changed but not view. The reason for this was the Link component used inside of SideBar component which was outside of the Router component. (Yes, I've exported SideBar with "withRouter", not worked). So, the solution was to move my SideBar component which holds, all Link components into my Router.

The problem is in my linkers, they are outside of my router

<div className="_wrapper">
  <SideBar /> // Holds my all linkers
  <Router>
     <Switch>
       <Route path="/" component={Home} />
       <Route path="/users" component={Users} />
     </Switch>
  </Router>
 </div>

Solution was moving my linkers into my router

<div className="_wrapper">
  <Router>
     <SideBar /> // Holds my all linkers
     <Switch>
       <Route path="/" component={Home} />
       <Route path="/users" component={Users} />
     </Switch>
  </Router>
</div>