Patrick
Patrick

Reputation: 847

React-router link doesn't work

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>
    );
  }

});

Upvotes: 13

Views: 31364

Answers (3)

Scratch&#39;N&#39;Purr
Scratch&#39;N&#39;Purr

Reputation: 10399

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])
}

Upvotes: 0

Artur Carvalho
Artur Carvalho

Reputation: 7157

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.

Upvotes: 13

Mark Anderson
Mark Anderson

Reputation: 663

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')
);

Upvotes: 12

Related Questions