Commit b9fec275b25f98781d4660df14367ab6e0246391
1 parent
36a4c235df
Exists in
master
add fix for active state bug
- Fixes issue where the active state for links wasn't updating. This is due to a bug in React and this implements a workaround which relies on setting { pure: false } on the main component container to prevent blocking re-renders when moving between routes (and leaving the active state on the old route). Hopefully this is fixed in the future as this isn't an ideal implementation.
Showing
5 changed files
with
25 additions
and
14 deletions
Show diff stats
imports/ui/components/app-navigation.js
1 | import React from 'react'; | 1 | import React from 'react'; |
2 | import { Navbar, Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; | 2 | import { Navbar, Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; |
3 | import { Link } from 'react-router'; | 3 | import { Link } from 'react-router'; |
4 | import { PublicNavigation } from './public-navigation'; | 4 | import { PublicNavigation } from './public-navigation'; |
5 | import { AuthenticatedNavigation } from './authenticated-navigation'; | 5 | import { AuthenticatedNavigation } from './authenticated-navigation'; |
6 | 6 | ||
7 | export class AppNavigation extends React.Component { | 7 | export class AppNavigation extends React.Component { |
8 | renderNavigation( hasUser, activeRoute ) { | 8 | renderNavigation( hasUser ) { |
9 | return hasUser ? <AuthenticatedNavigation activeRoute={ activeRoute } /> : <PublicNavigation activeRoute={ activeRoute } />; | 9 | return hasUser ? <AuthenticatedNavigation /> : <PublicNavigation />; |
10 | } | 10 | } |
11 | 11 | ||
12 | render() { | 12 | render() { |
13 | return <Navbar> | 13 | return <Navbar> |
14 | <Navbar.Header> | 14 | <Navbar.Header> |
15 | <Navbar.Brand> | 15 | <Navbar.Brand> |
16 | <Link to="/">Application Name</Link> | 16 | <Link to="/">Application Name</Link> |
17 | </Navbar.Brand> | 17 | </Navbar.Brand> |
18 | <Navbar.Toggle /> | 18 | <Navbar.Toggle /> |
19 | </Navbar.Header> | 19 | </Navbar.Header> |
20 | <Navbar.Collapse> | 20 | <Navbar.Collapse> |
21 | { this.renderNavigation( this.props.hasUser, this.props.activeRoute ) } | 21 | { this.renderNavigation( this.props.hasUser ) } |
22 | </Navbar.Collapse> | 22 | </Navbar.Collapse> |
23 | </Navbar>; | 23 | </Navbar>; |
24 | } | 24 | } |
25 | } | 25 | } |
26 | 26 |
imports/ui/components/authenticated-navigation.js
1 | import React from 'react'; | 1 | import React from 'react'; |
2 | import { browserHistory, IndexLink, Link } from 'react-router'; | 2 | import { browserHistory } from 'react-router'; |
3 | import { IndexLinkContainer, LinkContainer } from 'react-router-bootstrap'; | ||
3 | import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; | 4 | import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; |
4 | 5 | ||
5 | const handleLogout = () => { | 6 | const handleLogout = () => { |
6 | return Meteor.logout( () => browserHistory.push( '/login' ) ); | 7 | return Meteor.logout( () => browserHistory.push( '/login' ) ); |
7 | }; | 8 | }; |
8 | 9 | ||
9 | const userName = () => { | 10 | const userName = () => { |
10 | const user = Meteor.user(); | 11 | const user = Meteor.user(); |
11 | if ( user ) { | 12 | if ( user ) { |
12 | const name = user && user.profile ? user.profile.name : ''; | 13 | const name = user && user.profile ? user.profile.name : ''; |
13 | return `${ name.first } ${ name.last }`; | 14 | return `${ name.first } ${ name.last }`; |
14 | } | 15 | } |
15 | }; | 16 | }; |
16 | 17 | ||
17 | export const AuthenticatedNavigation = () => ( | 18 | export const AuthenticatedNavigation = () => ( |
18 | <div> | 19 | <div> |
19 | <Nav> | 20 | <Nav> |
20 | <li><IndexLink to="/" activeClassName="active">Index</IndexLink></li> | 21 | <IndexLinkContainer to="/"> |
21 | <li><Link to="/dashboard" activeClassName="active">Dashboard</Link></li> | 22 | <NavItem eventKey={ 1 } href="/">Index</NavItem> |
23 | </IndexLinkContainer> | ||
24 | <LinkContainer to="dashboard"> | ||
25 | <NavItem eventKey={ 2 } href="/dashboard">Dashboard</NavItem> | ||
26 | </LinkContainer> | ||
22 | </Nav> | 27 | </Nav> |
23 | <Nav pullRight> | 28 | <Nav pullRight> |
24 | <NavDropdown eventKey={ 3 } title={ userName() } id="basic-nav-dropdown"> | 29 | <NavDropdown eventKey={ 3 } title={ userName() } id="basic-nav-dropdown"> |
25 | <MenuItem eventKey={ 3.1 } onClick={ handleLogout }>Logout</MenuItem> | 30 | <MenuItem eventKey={ 3.1 } onClick={ handleLogout }>Logout</MenuItem> |
26 | </NavDropdown> | 31 | </NavDropdown> |
27 | </Nav> | 32 | </Nav> |
28 | </div> | 33 | </div> |
29 | ) | 34 | ) |
30 | 35 |
imports/ui/components/public-navigation.js
1 | import React from 'react'; | 1 | import React from 'react'; |
2 | import { Link } from 'react-router'; | 2 | import { LinkContainer } from 'react-router-bootstrap'; |
3 | import { Nav, NavItem } from 'react-bootstrap'; | 3 | import { Nav, NavItem } from 'react-bootstrap'; |
4 | 4 | ||
5 | export const PublicNavigation = () => ( | 5 | export const PublicNavigation = () => ( |
6 | <Nav pullRight> | 6 | <Nav pullRight> |
7 | <li role="presentation"><Link to="/signup">Sign Up</Link></li> | 7 | <LinkContainer to="signup"> |
8 | <li role="presentation"><Link to="/login">Log In</Link></li> | 8 | <NavItem eventKey={ 1 } href="/signup">Sign Up</NavItem> |
9 | </LinkContainer> | ||
10 | <LinkContainer to="login"> | ||
11 | <NavItem eventKey={ 2 } href="/login">Log In</NavItem> | ||
12 | </LinkContainer> | ||
9 | </Nav> | 13 | </Nav> |
10 | ) | 14 | ) |
11 | 15 |
imports/ui/containers/app-navigation.js
1 | import { createContainer } from 'meteor/react-meteor-data'; | 1 | import { composeWithTracker } from 'react-komposer'; |
2 | import { AppNavigation } from '../components/app-navigation'; | 2 | import { AppNavigation } from '../components/app-navigation'; |
3 | 3 | ||
4 | export default createContainer( ( { params } ) => { | 4 | const composer = ( props, onData ) => { |
5 | return { hasUser: Meteor.user() }; | 5 | onData( null, { hasUser: Meteor.user() } ); |
6 | }, AppNavigation ); | 6 | }; |
7 | |||
8 | export default composeWithTracker( composer, {}, {}, { pure: false } )( AppNavigation ); | ||
7 | 9 |
package.json
1 | { | 1 | { |
2 | "name": "application-name", | 2 | "name": "application-name", |
3 | "version": "1.0.0", | 3 | "version": "1.0.0", |
4 | "description": "Application description.", | 4 | "description": "Application description.", |
5 | "scripts": { | 5 | "scripts": { |
6 | "start": "meteor --settings settings-development.json", | 6 | "start": "meteor --settings settings-development.json", |
7 | "chimp-watch": "chimp --ddp=http://localhost:3000 --watch --mocha --path=tests", | 7 | "chimp-watch": "chimp --ddp=http://localhost:3000 --watch --mocha --path=tests", |
8 | "chimp-test": "chimp --ddp=http://localhost:3000 --mocha --path=tests", | 8 | "chimp-test": "chimp --ddp=http://localhost:3000 --mocha --path=tests", |
9 | "staging": "meteor deploy staging.meteor.com --settings settings-development.json", | 9 | "staging": "meteor deploy staging.meteor.com --settings settings-development.json", |
10 | "production": "meteor deploy production.meteor.com --settings settings-production.json" | 10 | "production": "meteor deploy production.meteor.com --settings settings-production.json" |
11 | }, | 11 | }, |
12 | "devDependencies": {}, | 12 | "devDependencies": {}, |
13 | "dependencies": { | 13 | "dependencies": { |
14 | "chimp": "^0.33.0", | 14 | "chimp": "^0.33.0", |
15 | "react": "^0.14.8", | 15 | "react": "^0.14.8", |
16 | "react-addons-pure-render-mixin": "^0.14.8", | 16 | "react-addons-pure-render-mixin": "^0.14.8", |
17 | "react-bootstrap": "^0.28.4", | 17 | "react-bootstrap": "^0.28.4", |
18 | "react-dom": "^0.14.7", | 18 | "react-dom": "^0.14.7", |
19 | "react-mounter": "^1.1.0", | 19 | "react-komposer": "^1.7.1", |
20 | "react-router": "^2.0.1", | 20 | "react-router": "^2.0.1", |
21 | "react-router-bootstrap": "^0.20.1" | 21 | "react-router-bootstrap": "^0.20.1" |
22 | } | 22 | } |
23 | } | 23 | } |
24 | 24 |