1

I have a React app with following simplified structure:

function App(props) {
    return (
        <Navbar />
        <Router>
            <Route exact path="/profile/" component={Profile} />
            <Route exact path="/" component={Home} />
        </Router>
    );
}

In Navbar component I have a button for logout, meaning that I need to:

  1. Delete Authentication token from Storage (simply do a logic for general case), and
  2. Route user to the login page.

I tried to use onClick of that button and use this.props.history.push('/') to change the path, but this doesn't work (it complains that history is undefined), since my navbar is defined outside the Router.

My question is, is it okay to move Navbar to inside of my Router components and repeat it while it is the same in all of pages? Or is there any duplicate-proof solution I can use to change my browser path?

2
  • 1
    I think it is fine to put it inside the router, i dont think Navbar will rerender if the route changed. Commented May 8, 2020 at 18:37
  • Thanks, your mention about Navbar not being rendered on changing route helped a lot. Commented May 8, 2020 at 23:24

3 Answers 3

2

It is fine to insert <Navbar> into the Router. My setup tends to be

<Router>
    <div className="app-container">
      <Navigation />
      <div className="content">
        <Switch>
          (Routes go here)
        </Switch>
      </div>
    </div>
</Router>
Sign up to request clarification or add additional context in comments.

4 Comments

How can I access history inside Navigation now? I is undefined for me. (Should I pass any props to Navigation?
Use the useHistory hook.
If Navbar is not a function component, what can I do?
You can use the withRouter() function, then use with this.props.history. More info here: reacttraining.com/react-router/web/api/withRouter
2

Yes! Try using <Switch>in router and <Link> inside your Navbar

export default function App() {
  return (
    <Router>
      <Navbar />
        // inside Navbar try using <Link to="/">Logout</Link>
        {/* A <Switch> looks through its children <Route>s and
            renders the first one that matches the current URL. */}
        <Switch>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/users">
            <Users />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch> 
    </Router>
  );
}

https://reacttraining.com/react-router/web/guides/quick-start

3 Comments

Can I access to history object in Navbar now? Because I don't want to use Link to simply redirect to home, I want to also clear my Authentication in Storage.
Since u r using function component, you can try const { history } = useHistory(); then u can access the history without any problem. Give it a try.
@WesleyLoh Thanks. In this case, did I ever need to include Navbar in Router?
0

The routes listen to the history api provided by the Router context and since Navbar is rendered outside of it they don't reflect the change.

The solution is to wrap Router around navbar and also render NAvbar as a default route

function App(props) {
    return (
       <Router>
          <>
            <Route component={Navbar}/>
            <Route exact path="/profile/" component={Profile} />
            <Route exact path="/" component={Home} />
          </>
        </Router>
    );
}

3 Comments

I don't know why somebody downvoted your answer (I'd be happy if I know what's wrong here), but I ended up with a similar solution to pass Route's props to my Navbar to have history access: <Route render={(props) => (<Nabvar {...props} />)} />
@AliTou, Rendering Navbar as a Route is required so that the Router Props are available to it
Yeah, this is what other answers didn't consider.

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.