2

I am trying to understand why Header component doesn't get updated when I click Button. I believe that the problem is that I am not calling with Router. But why then App.js doesn't re render when I switch routes?

import React, { useEffect } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import First from './First';
import Second from './Second';
import Third from './Third';
import Header from './Header';

function App() {
  return (
    <div>
      <Header />
      <Router>
        <Switch>
          <Route exact path={'/'} component={First} />
          <Route exact path={'/first'} component={Second} />
          <Route exact path={'/second'} component={Third} />
        </Switch>
      </Router>
    </div>
  );
}

export default App;





import React from 'react';

export default function First(props) {
  console.log(' ~ file: First.js ~ line 4 ~ First ~ props', props);
  return (
    <div>
      First
      <button
        onClick={() => {
          props.history.push({
            pathname: '/second',
          });
        }}
      >
        Go to Second
      </button>
    </div>
  );
}

so my condition here doesn't get fired when path changes. the reason is that component hasn't been called and old condition is still there

import React from 'react'

export default function Header() {
    console.log(window.location.pathname);
    const logger = window.location.pathname === '/third' ? (<div>This is second</div>) : 
    (<div>this is root</div>)
    return logger
}

I know that I can call Header somewhere else, but what is problem in this showcase?

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
Sonny49
  • 425
  • 3
  • 18

1 Answers1

3

The Header component is being rendered outside the Router, so it's not rerendered or made aware of route changes.

I suggest moving the Header component into the Router and have it access the route props.

App

function App() {
  return (
    <div>
      <Router>
        <Header /> // <-- move into Router
        <Switch>
          <Route exact path={'/'} component={First} />
          <Route exact path={'/first'} component={Second} />
          <Route exact path={'/second'} component={Third} />
        </Switch>
      </Router>
    </div>
  );
}

Header

import { useLocation } from 'react-router-dom';

export default function Header() {
  const location = useLocation();

  console.log(location.pathname);

  return location.pathname === '/third' 
    ? <div>This is second</div>
    : <div>this is root</div>;
}

Edit header-component-doesnt-get-updated-after-route-change

Alternatively you could use the useRouteMatch hook:

import { useRouteMatch } from 'react-router-dom';

export default function Header() {
  const match = useRouteMatch('/third');

  return match 
    ? <div>This is second</div>
    : <div>this is root</div>;
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • Hi Drew, thank you for your answer, but I've tested it and don't see any changes. – Sonny49 Oct 08 '21 at 05:50
  • this a suggestion to use HOC here https://stackoverflow.com/questions/55175724/proper-way-of-handling-conditional-component-render-depending-on-route – Sonny49 Oct 08 '21 at 05:58
  • @Sonny49 It's working from what I can tell. I added a link to a codesandbox in my answer, but it is as well: https://codesandbox.io/s/header-component-doesnt-get-updated-after-route-change-nmeib. Navigating to "/third" updates what the header renders. – Drew Reese Oct 08 '21 at 05:59
  • @Sonny49 Sorry, I don't see how a Higher Order Component helps here. – Drew Reese Oct 08 '21 at 06:01