Matthias
Matthias

Reputation: 11

Migration react-router v5 to v6 dynamic tab navigation

I've got some problems upatading to react router v6 within my common component with tab navigation.

The url looks like:

I've got a base route like home, settings,... At the end, the name of the tab is added:

 tabs={[
      {
        label: t("navigations.firsttab"),
        path: "firsttab",
      },
      {
        label: t("navigations.secondtab"),
        path: "secondtab",
      },
    ]}

This results in:

My working code of the shared component (tabs) in v5:

const history = useHistory();
  const { classes } = useStyles();
  const handleChange = (event: React.ChangeEvent, newValue: string) => {
    history.push(newValue);
  };
  const { url } = useRouteMatch();
  return (
    <>
      <Tabs
        className={classes.tabContainer}
        centered={alignCenter}
        disableripple={`${disableRipple}`}
        indicatorColor={underlineColor}
        onChange={handleChange}
        orientation={orientation}
        scrollButtons="auto"
        textColor={tabTextColor}
        value={history.location.pathname}
        variant={tabVariant}
        {...tabContainerProps}
      >
        {tabs.length > 0
          ? tabs.map((item) => {
              return (
                <Tab
                  classes={{
                    selected: classes.tabSelected,
                    root: classes.tabRoot,
                    // button: classes.tab,
                    wrapper: classes.tabLabel,
                    wrapped: classes.tabLabel,
                  }}
                  disableRipple={disableRipple}
                  icon={item.icon}
                  key={item.path}
                  label={item.label}
                  {...tabProps}
                  wrapped={wrapTabLabel}
                  value={`${url}${item.path}`}
                />
              );
            })
          : null}
      </Tabs>

My code in v6:

  const navigate = useNavigate();
  const location = useLocation();
  const { classes } = useStyles();
  const handleChange = (event: React.ChangeEvent, newValue: string) => {
    navigate(newValue);
  };
  const url = location.pathname; //not the same like useRouteMatch and therfore not working... I don't find the solution regarding useMatch 
  return (
    <>
      <Tabs
        className={classes.tabContainer}
        centered={alignCenter}
        disableripple={`${disableRipple}`}
        indicatorColor={underlineColor}
        onChange={handleChange}
        orientation={orientation}
        scrollButtons="auto"
        textColor={tabTextColor}
        value={location.pathname}
        variant={tabVariant}
        {...tabContainerProps}
      >
        {tabs.length > 0
          ? tabs.map((item) => {
              return (
                <Tab
                  classes={{
                    selected: classes.tabSelected,
                    root: classes.tabRoot,
                    // button: classes.tab,
                    wrapper: classes.tabLabel,
                    wrapped: classes.tabLabel,
                  }}
                  disableRipple={disableRipple}
                  icon={item.icon}
                  key={item.path}
                  label={item.label}
                  {...tabProps}
                  wrapped={wrapTabLabel}
                  value={`${url}${item.path}`} //I do not find a solution to get the url like useRouteMatch() does. item.path is the subpath of the tab, e.g. firsttab (domain.com/home/firsttab)
                />
              );
            })
          : null}
      </Tabs>

How can I resolve the url like useRouteMatch?

Upvotes: 1

Views: 1208

Answers (1)

Drew Reese
Drew Reese

Reputation: 203099

react-router-dom v6 is capable of using relative routing, this is why the useMatch hook isn't a one-to-one replacement to the v5 useRouteMatch hook.

You don't need to grab the url prefix to do the navigation, navigate can handle navigating relatively to sibling routes. So long as the sibling path values are unique, it can work as a tab value.

tabs={[
  {
    label: t("navigations.firsttab"),
    path: "firsttab",
  },
  {
    label: t("navigations.secondtab"),
    path: "secondtab",
  },
]}

...

const navigate = useNavigate();
const { classes } = useStyles();
const handleChange = (event: React.ChangeEvent, newValue: string) => {
  navigate(newValue); // "/home/firsttab" <-> "/home/secondtab"
};

return (
  <>
    <Tabs
      ...
      onChange={handleChange}
      ...
    >
      {tabs.map((item) => {
        return (
          <Tab
            ...
            value={`../${item.path}`} // "/home/firsttab" <-> "/home/secondtab"
          />
        );
      })}
    </Tabs>
  </>
);

Upvotes: 1

Related Questions