简体   繁体   中英

React: tracking history changes by history.push in common component

I have a Layout component which wraps the rest of my application. The default route is a page with multiple buttons, implemented as a small component called NavButton, which use history.push to go to a new route. Then in my Layout component, there are 2 buttons, but one of them should change depending on which route we are currently navigated to. So when we are on the main page, the button should say ie "Change Code", but on any other page, it should say "Back". I tried it in the following way:

Layout.tsx:

interface ILayoutProps {
  children: ReactNode;
}

const Layout: React.FC<ILayoutProps> = ({ children }) => {
  const currentRoute = useLocation();

  useEffect(() => {
    console.log(currentRoute);
  }, [currentRoute]);

  const logout = () => {
    console.log('logout');
  };

  return (
    <div>
      <div>{children}</div>
      <Grid container spacing={2}>
        <Grid item xs={6}>
          {currentRoute.pathname === '/' ? (
            <NavButton displayName="Change Code" route="/change-code" variant="outlined" />
          ) : (
            <Button variant="outlined" color="primary" fullWidth>
              Back
            </Button>
          )}
        </Grid>
        ...
      </Grid>
    </div>
  );
};

export default Layout;

NavButton.tsx:

interface NavButtonProps {
  displayName: string;
  route: string;
  variant?: 'text' | 'outlined' | 'contained';
}

const NavButton: React.FC<NavButtonProps> = ({ displayName, route, variant = 'contained' }) => {
  const history = useHistory();

  const navigatePage = () => {
      history.push(route);
      // Also tried it like this:
      // setTimeout(() => history.push(route), 0);
  };

  return (
    <Button
      variant={variant}
      color="primary"
      onClick={() => navigatePage()}
      fullWidth
    >
      {displayName}
    </Button>
  );
};

export default NavButton;

SO in my Layout, I am trying to keep track of location changes with the useLocation() hook, but when a button is pressed, and thus history.push(route) is called, it doesn't get detected by the hook in Layout. I've also tried to use the useHistory() hook and call the listen() method on it, but same problem. Also, my router is a BrowserRouter, not sure if that is of any help... What am I missing here?

So the issue was that I had my App component defined like this:

<Layout>
    <Routes />
</Layout>

And my Routes looked like this:

<BrowserRouter>
    <Switch>
        <Route ...>
        ....
    </Switch>
</BrowserRouter>

The useLocation() hook in my Layout wasn't working since it was not a child of my BrowserRouter. Changing it to be like that made the code work.

Only thing I find weird is that in my app, I didn't get an error for invalid hook call, but in the sandbox I did. Maybe I need to upgrade my React packages...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM