4

In my project I have a TabComponent which displays 3 tabs: home, popular, all.

Now, I am using context of react to maintain:

  1. activetab which stores current tab.
  2. toggleTab method which changes activetab using setState.

TabComponent

import React, {Component} from 'react'
import Context from '../../provider'
import {Nav, NavItem, NavLink} from 'reactstrap'
import {Redirect} from 'react-router-dom'
import classnames from 'classnames'

export default class TabComponent extends Component {
    render() {
        return (
            <Context.Consumer>
                {context => (
                    <Nav tabs color='primary'>
                        <NavItem>
                            <NavLink
                                className={classnames({ active: context.activeTab === '1' })}
                                onClick={() =>{context.toggleTab('1')}}
                            >
                            Home
                            </NavLink>
                        </NavItem>
                        <NavItem>
                            <NavLink
                                className={classnames({ active: context.activeTab === '2' })}
                                onClick={() => {context.toggleTab('2')}}
                            >
                            Popular
                            </NavLink>
                        </NavItem>
                        <NavItem>
                            <NavLink
                                className={classnames({ active: context.activeTab === '3' })}
                                onClick={() => {context.toggleTab('3')}}
                            >
                            All
                            </NavLink>
                        </NavItem>                
                    </Nav>
                )}
            </Context.Consumer>
        )
    }
}

What I want to achieve is, onClick should also change the URL.

  • For tab 1, the url should be \home\
  • For tab 2, the url should be \popular\
  • For tab 3, the url should be \all\

Using this.props.history in the onClick method is not working with export default withRouter(TabComponent).

<NavLink
    className={classnames({ active: context.activeTab === '1' })}
    onClick={() =>{
        context.toggleTab('1');
        this.props.history('/home/');
    }}
>

Error:

You should not use <Route> or withRouter() outside a <Router>


window.location in onClick:

<NavLink
    className={classnames({ active: context.activeTab === '1' })}
    onClick={() =>{
        context.toggleTab('1');
        window.location = '/home/';
    }}
>

This actually works but the behaviour is not good.

Clicking the tab does the following:

  1. It Changes the content of body using context.toggleTab.
  2. Then it changes the URL using window.location.
  3. Since, the URL changed, the page is getting reloaded.

The problem here is the content is already loaded in the 1st step. Using window.location changes the URL but also re-loads the page which is not required. It there a way to do skip the 3rd step or is that any other method which just changes the URL?

7
  • 1
    If you are using react-router , you can use this.props.history(url). Else you can use window.location = url. Commented Jul 6, 2018 at 8:16
  • I am unsure on where to write this.props.history(url)!! Commented Jul 6, 2018 at 8:17
  • You can either write it in your onClick function or in the toggle function. Both would work i guess Commented Jul 6, 2018 at 8:19
  • I am getting error if i do that, I have updated my question. Commented Jul 6, 2018 at 8:24
  • That is because TabComponent is not rendered by <Route>. So you can use window.location = url instead of this.props.history Commented Jul 6, 2018 at 8:31

1 Answer 1

3

Your TabComponent does not have access to the React Router history route prop because it's probably not used as a component given to a Route.

You could use withRouter on your TabComponent to get access to the route props.

class TabComponent extends Component {
    render() {
      // ...
    }
}

export default withRouter(TabComponent);

You also must make sure that you have a Router component at the top of your app.

Example

class App extends Component {
  render() {
    return (
      <BrowserRouter>
        {/* ... */}
      </BrowserRouter>
    );
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

That did do the trick, I didn't quite understand why we need to have a BrowserRouter at top level?
@SreekarMouli withRouter uses values from the context supplied by the Router component, so if a component using the withRouter HOC is rendered outside of the Router, it cannot get the proper information it needs.

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.