0

I am working on a reactjs application - and I've created two menus - header/footer -- I've noticed a bug on the "active" state when I navigate on the pages.

// Current problems

  1. When arriving on home page the home link is active on the header menu, but when clicking on the footer menu - privacy - the privacy link is active but the header links are also still active when they should be deactived.
  2. Also when going to a page that doesn't exist like typing /home2 -- it should bounce to the Error page but it doesn't - what is interfering with this in the router?

// Land on home page -- home page is active enter image description here

// Land on privacy - privacy is active in the footer - but the home page in the header is also still active.

enter image description here

// Header.js

import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import { Row, Col, Menu, Icon, Alert } from 'antd'

const SubMenu = Menu.SubMenu;
const MenuItemGroup = Menu.ItemGroup;

// this is a class because it needs state
class Header extends Component {

  state = {
    current: 'home',
  }

  handleClick = (e) => {
    console.log('click ', e);
    this.setState({
      current: e.key,
    });
  }

  componentDidMount() {    

  }

  render() {
    return (
      <Menu
        onClick={this.handleClick}
        selectedKeys={[this.state.current]}
        mode="horizontal"
      >
        <Menu.Item key="home">
          <Link to="/home" rel="noopener noreferrer">Home</Link>
        </Menu.Item>
        <Menu.Item key="account">
          <Link to="/account" rel="noopener noreferrer">Account</Link>
        </Menu.Item>
      </Menu>
    )
  }
}

export default Header

// Footer.js

import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import { Row, Col, Menu, Icon, Alert } from 'antd'

const SubMenu = Menu.SubMenu;
const MenuItemGroup = Menu.ItemGroup;

// this is a class because it needs state
class Footer extends Component {

  state = {
    current: 'home',
  }

  handleClick = (e) => {
    console.log('click ', e);
    this.setState({
      current: e.key,
    });
  }

  componentDidMount() {    

  }

  render() {
    return (
      <Menu
        onClick={this.handleClick}
        selectedKeys={[this.state.current]}
        mode="horizontal"
      >
        <Menu.Item key="about">
          <Link to="/about" rel="noopener noreferrer">About</Link>
        </Menu.Item>
        <Menu.Item key="terms">
          <Link to="/terms" rel="noopener noreferrer">Terms of Service</Link>
        </Menu.Item>
        <Menu.Item key="privacy">
          <Link to="/privacy" rel="noopener noreferrer">Privacy Policy</Link>
        </Menu.Item>
      </Menu>
    )
  }
}

export default Footer

// router.js

import React, { Component } from 'react'
import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom'
import createBrowserHistory from 'history/createBrowserHistory'
import { Provider } from 'react-redux'
import { createStore, compose } from 'redux'

// components
import Login from './components/Login/Login'

import Home from './components/Home/Home'
import Account from './components/Account/Account'

import About from './components/About/About'
import Terms from './components/Terms/Terms'
import Privacy from './components/Privacy/Privacy'

import Error from './components/Error/Error'

import Header from './components/Header/Header'
import Footer from './components/Footer/Footer'

const history = createBrowserHistory()

//const store = createStore(rootReducer, compose(
const store = createStore(compose(
  typeof window === 'object' && typeof window.devToolsExtension !== 'undefined' ? window.devToolsExtension() : (f) => f
  )
)

// we can pass the lang files as props to the routes
// we should have a nested route inside service here to show the other services page

class Routes extends Component {
  render () {
    return (
      <Provider store={store}>
        <Router history={history}>
          <div className='off-canvas-wrap' data-offcanvas>
            <div className='inner-wrap'>
              <Header transparent />
              <Switch>
                <Route path='/home' component={Home} />
                <Route path='/account' component={Account} />

                <Route path='/about' component={About} />
                <Route path='/terms' component={Terms} />
                <Route path='/privacy' component={Privacy} />

                <Route path='/login' component={Login} />
                <Route path='/' component={Login} />
                <Route component={Error} />
              </Switch>
              <Footer transparent />
            </div>
          </div>
        </Router>
      </Provider>
    )
  }
}

export default Routes
B--rian
  • 5,578
  • 10
  • 38
  • 89
The Old County
  • 89
  • 13
  • 59
  • 129

2 Answers2

0

If you are using react router 4

you can use NavLink. It providing the activeClassName and activeStyle options for adding class and activeStyle

activeClassName

<NavLink to="/about" activeClassName="selected">about </NavLink>

activeStyle

<NavLink
  to="/about"
  activeStyle={{
    color: 'red'
   }}
>about</NavLink>

Also when going to a page that doesn't exist like typing /home2 -- it should bounce to the Error page but it doesn't - what is interfering with this in the router?

The issue is here :

<Route path='/' component={Login} />

In case no route is match,it will render to Login component and not a Error component

You must add exact to Route to get 404 behaviour of Error component.

Correct way to do this.

<Route exact path='/' component={Login} />
RIYAJ KHAN
  • 15,032
  • 5
  • 31
  • 53
  • - but it's using antd menu -- I suppose for the footer I could use NavLink -- but for the header use menu -- I also want to configure the header menu to compact on responsive – The Old County Aug 27 '17 at 14:46
  • -- I see -- yes I had it as / for the login page -- but you are saying I should do the exact path for the login page -- ok should I have it just /login - and use a redirect on / ? -- I only want them to bounce to the login page if they are NOT logged in -- otherwise I suppose the home page is where they would go – The Old County Aug 27 '17 at 17:15
  • `should I have it just /login - and use a redirect on / ?` yes.Jst bounce to /ogin if no login – RIYAJ KHAN Aug 27 '17 at 17:17
  • -- ok - could you do a demo of this - if logged in/not logged bounce -- import { Route, Redirect } from 'react-router' ( loggedIn ? ( ) : ( ) )}/> – The Old County Aug 27 '17 at 17:24
  • https://stackoverflow.com/questions/34735580/how-to-do-a-redirect-to-another-route-with-react-router – The Old County Aug 27 '17 at 17:24
  • Also - should I remove the menu in the footer for the NavLink parts -- I think I still need a way to deselect the header menu antd -- so its not on the page it handles not to select any link? – The Old County Aug 27 '17 at 17:25
  • -- I've also seen methods to do a pushstate? - https://stackoverflow.com/questions/29594720/automatic-redirect-after-login-with-react-router – The Old County Aug 27 '17 at 17:25
  • -- documentation on the NavLink and Link -- https://reacttraining.com/react-router/web/api/Link – The Old County Aug 27 '17 at 17:26
  • ok so how would I deselect the header menu if I've clicked on footer links or refreshed the page on footer links? I have tried to SET the state from the routing level -- checking on which page the user is on and feeding it into the header and footer components -- http://jsfiddle.net/0ht35rpb/105/ – The Old County Aug 28 '17 at 11:15
  • I need your assistance on a register form -- https://stackoverflow.com/questions/45942891/reactjs-redux-storing-data-from-a-form-submission – The Old County Aug 29 '17 at 16:15
  • @TheOldCounty sure – RIYAJ KHAN Aug 31 '17 at 04:34
0

The problem is in your route component this line arises issue:-

 <Route path='/' component={Login} />

it must be like

<Route exact path='/' component={Login} />

if you won't use the exact attribute, every time it will match with the routing /. So you need to add an exact keyword to avoid this issue.

Shashwat Prakash
  • 434
  • 5
  • 14