13

React-router is off to a really bad start... What seems basic doesn't work. Using react-router 2.0.0 my Link component updates the URL to be /about, but my page doesn't render the About component after that...

Entry point js

var React = require('react');
var ReactDOM = require('react-dom');
var Router = require('react-router').Router;
var Route = require('react-router').Route;
var hashHistory = require('react-router').hashHistory;
var App = require('./components/App.react');
var About = require('./components/About');

ReactDOM.render(
    <Router history={hashHistory} >
        <Route path="/" component={App}>
            <Route path="about" component={About} />
        </Route>
    </Router>, 
    document.getElementById('app')
);

App.js

'use strict';

var React = require('react');
var Link = require('react-router').Link;
var Header = require('./Header');
var UserPanel = require('./UserPanel');
var ModelPanel = require('./ModelPanel.react');
var EventPanel = require('./event/EventPanel');
var VisPanel = require('./vis/VisPanel');
var LoginForm = require('./LoginForm');
var AppStore = require('../stores/AppStore');
var AppStates = require('../constants/AppStates');

var App = React.createClass({

  [... code omitted ...]

  render: function() {
    var viewStateUi = getViewStateUi(this.state.appState);

    return (
      <div>
        <Header />
        <Link to="/about">About</Link>
        {viewStateUi}
      </div>
    );
  }

});

3 Answers 3

13

For some reason, the <Link>s were not working for me with the configuration below.

// index.js

ReactDOM.render(
  <Provider store={store}>
    <BrowserRouter >
      <App />
    </BrowserRouter>
  </Provider>,
  document.getElementById('root')
);

// App.js

  return (
      <div className="App">
        <Route exact={true} path="/:lang" component={Home} />
        <Route exact={true} path="/" render={() => <Redirect to={{ pathname: 'pt' }} />} />
        <Route path="/:lang/play" component={Play} />} />
        <Route path="/:lang/end" component={End} />
      </div >
    );

The Home component had the Link, but Links on the App would do the same. Every time I clicked it, it would only change the url, but the views would stay the same.

I was able to put it working when I added withRouter to the App.js

export default withRouter(connect(mapStateToProps, { f, g })(App));

I still don't understand what happened. Maybe it's related with redux or there is some detail I'm missing.

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

1 Comment

You were right it is related to Redux be cause I've just had the same problem with MobX. The thing is that MobX/Redux takes control of shouldComponentUpdate so the App component does not re-render be cause it does not receive the location as a prop. More explanations in the documentation here : github.com/ReactTraining/react-router/blob/master/packages/…
12

Since the 'About' route is a child of the 'App' route, you need to either add this.props.children to your App component:

var App = React.createClass({

 render: function() {

   var viewStateUi = getViewStateUi(this.state.appState);

    return (
      <div>
        <Header />
        <Link href="/about">About</Link>
        {viewStateUi}
        {this.props.children}
      </div>
    );
  }
});

or separate your routes:

ReactDOM.render(
  <Router history={hashHistory} >
    <Route path="/" component={App} />
    <Route path="/about" component={About} />
  </Router>, 
  document.getElementById('app')
);

2 Comments

Awesome, I'll test tonight and read all the docs - that's pretty obvious in retrospect.
It works, but I don't why it works by adding '{this.props.children}' in App. Why without it, it doesn't work ? Please
0

None of the solutions worked for me, including adding withRouter to my Component. I was experiencing the same issue where the browser's address bar updates the URL but the component doesn't render. During the debugging of my issue, I realize I have to present the context of my problem because it is a bit different from what the OP had.

The route I was trying to get to work was a dynamic route that takes an arbitrary parameter, e.g.

<Route path={`/hr/employees/:id`} component={EmployeePage} />

The component this route uses is "self-referential", meaning that within the component or its children components, they have a Link component that directs to /hr/employees/:id, but with a different id. So let's say if I was at /hr/employees/3 and on the page, there was a link to /hr/employees/4, e.g. <Link to='/hr/employees/4'>, I would get this problem where the component didn't re-render.

To solve this problem, I simply modified the componentDidUpdate method of my EmployeePage component:

componentDidUpdate(prevProps) {
  if (this.props.match.params.id !== prevProps.match.params.id) {
    // fetch data
  }
}

If you're using functional components, use useEffect:

const EmployeePage = props => {
  const {id} = props.match.params
  
  useEffect(() => {
    // fetch data
  }, [id])
}

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.