Reputation: 3290
I cannot get activeClassName
to render correctly in my Navigation component Link. This has been tracked down to the following symptoms:
In the following code, the Navigation component is not getting a props.route
passed to it at all. The App component has a props.route
, however it is never updated as the user navigates to other routes. It is always set to the first route that was loaded. The componentWillReceiveProps
is fired when changing routes, as the props.children
is changing.
Here are the relevant snippets of my files:
app.jsx
import router from 'app/router';
[...]
ReactDOM.render(
<Provider store={store}>
{router}
</Provider>,
document.getElementById('app')
);
router/index.jsx
export default (
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={GameBoard}/>
<Route path="profile" component={ProfileBoard}/>
<Route path="profile/:userId" component={ProfileBoard}/>
<Route path="help" component={Help}/>
<Route path="about" component={About}/>
</Route>
</Router>
);
App.jsx
import React from 'react';
import Navigation from 'Navigation';
export default class App extends React.Component {
static propTypes = {};
constructor(props) {
super(props);
}
render() {
return (
<div>
<Navigation />
<div className="content">
{this.props.children}
</div>
</div>
);
}
};
Navigation.jsx
import React from 'react';
import {connect} from 'react-redux';
import {IndexLink, Link} from 'react-router';
export class Navigation extends React.Component {
static propTypes = {};
constructor(props) {
super(props);
}
render() {
return (
<div className="top-bar navigation">
<div className="row">
<div className="small-12 columns">
<div className="top-bar-left">
<ul className="menu">
<li className="menu-text">
TVDeadpool.xyz
</li>
<li>
<IndexLink to="/" activeClassName="link-active">Bets</IndexLink>
</li>
<li>
<Link to="/help" activeClassName="link-active">Help</Link>
</li>
<li>
<Link to="/about" activeClassName="link-active">About</Link>
</li>
</ul>
</div>
</div>
</div>
</div>
);
}
}
export default connect()(Navigation);
Navigation.jsx has been simplified. I removed some functionality that shows a Logout link if you are logged in, and handles that link. That is the reason I am including connect
, though.
I am pouring through the documentation for react-router but cannot for the life of me figure out where I am going wrong. It must be something to do with nesting within the <Provider/>
, I guess? Any help would be appreciated!
Note that if you want to see this in (in)action, check out TVDeadpool.xyz. Not a plug, just a fact.
UPDATE
Here is a hack fix:
App.jsx
import React from 'react';
import Navigation from 'Navigation';
export default class App extends React.Component {
static propTypes = {};
constructor(props) {
super(props);
}
render() {
return (
<div>
<Navigation location={this.props.location.pathname}/>
<div className="content">
{this.props.children}
</div>
</div>
);
}
};
Simply adding that location
prop to <Navigation/>
causes a re-render, without any additional code.
I think the reason this is happening is that App is always considered to be at route.path
of "/", no matter what route is actually showing. Its immediate children seem to get the appropriate route.path
, but Navigation, being a nested component of App, does not. In fact, it does not receive a route
prop at all because it is not directly referenced by a <Route/>
.
That said, how would this ever work? Should you not be able to simple include Link and expect it to work as described? I feel like I am missing something key to how react-router is supposed to work.
Upvotes: 1
Views: 1358
Reputation: 89
I think the reason activeClassName is not working is because you are using connect
export default connect()(Navigation);
See this issue... https://github.com/reactjs/react-redux/issues/388
It is reported as fixed in React Router 3.0.0-alpha.1 and newer.
Another hack fix I found you can use in older versions of react router is to pass {pure : false} to tell connect it is not a pure component...
export default connect(mapStateToProps, null, null, { pure: false })(Navigation);
Upvotes: 4