How to create react tab navbar links with fragment identifiers (hash links)?

1k views Asked by At

I have created a page with some tabs on it. Tab codes are these:

const [ toggleState, setToggleState ] = useState(1);

const toggleTab = (index) => {
 setToggleState(index);
}

<div className="tab-title-Container">
 <li className= {toggleState === 1 ? "tab-name active-name" : "tab-name"} 
  onClick={() => toggleTab(1)}>Tab1</li>
 <li className= {toggleState === 2 ? "tab-name active-name" : "tab-name"} 
  onClick={() => toggleTab(2)}>Tab2</li>
</div>
<div className="tab-content-Container">
 <div className= {toggleState === 1 ? "tab-content active-content" : "tab-content"}>
  Tab1 Content</div>
 <div className= {toggleState === 2 ? "tab-content active-content" : "tab-content"}>
  Tab2 Content</div>
</div>

style:
.tab-content {display: none;}
.active-content {display: block;}

Now I want to create navbar links of each tab. When I click Tab2 navbar link, this page should open and Tab2 switch to active class (default active tab is Tab1). I am using react-router-dom": "^6.3.0".

I need to create routes like this "https://example.com/page=01#tab1", "https://example.com/page=01#tab2" for them.

1

There are 1 answers

5
Drew Reese On

react-router-hash-link AFAIK hasn't been updated to be compatible with react-router-dom@6. That said, it doesn't appear you are using the hash for normal purposes. The URL hash value can be read from the location object and parsed to extract the numerical tab value. Use a useEffect hook to "listen" for changes to the hash to update the local toggleState state.

Example:

import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";

const Page = () => {
  const { hash } = useLocation();

  const [toggleState, setToggleState] = useState(1);

  useEffect(() => {
    setToggleState(Number(hash.slice(4))); // hash is "#tabX" so strip first 4 chars
  }, [hash]);

  const toggleTab = (index) => {
    setToggleState(index);
  };

  return (
    ...
  );
};

...

<Link to="/1#tab1">Page 1 tab 1</Link>
<Link to="/1#tab2">Page 1 tab 2</Link>
<Link to="/2#tab1">Page 2 tab 1</Link>
<Link to="/2#tab2">Page 2 tab 2</Link>

Edit how-to-create-react-tab-navbar-links-with-fragment-identifiers-hash-links

Like I said, this is a bit of an odd use of the URL hash. I think a query parameter would be an improved alternative.

Example:

import { useEffect, useState } from "react";
import { useSearchParams } from "react-router-dom";

const Page = () => {
  const [searchParams, setSearchParams] = useSearchParams();
  const { pageId } = useParams();

  const [toggleState, setToggleState] = useState(1);

  useEffect(() => {
    // access tab query parameter
    const tab = searchParams.get("tab");
    if (tab) {
      // synchronize local state
      setToggleState(Number(tab));
    } else {
      // redirect to correct tab
      searchParams.set("tab", 1);
      setSearchParams(searchParams, { replace: true });
    }
  }, [searchParams, setSearchParams]);

  const toggleTab = (index) => {
    setToggleState(index);
  };

  return (
    ...
  );
};

...

<Link to="/1?tab=1">Page 1 tab 1</Link>
<Link to="/1?tab=2">Page 1 tab 2</Link>
<Link to="/2?tab=1">Page 2 tab 1</Link>
<Link to="/2?tab=2">Page 2 tab 2</Link>

Edit how-to-create-react-tab-navbar-links-with-fragment-identifiers-hash-links (forked)