I'm still quite new to Typescript and react and unfortunately don't understand what I'm doing wrong. I have a tab style nav with a NavDropdown. Unfortunately the dropdown is the only tab that does not get the active class when one of the dropdown items is selected. I have already seen that some people had this problem and could solve it somehow but I can't find a way to do it in my case. Can anyone help me?
Currently my nav looks like this:
<Nav variant="tabs">
<Nav.Item>
<Nav.Link
onClick={(e: React.MouseEvent<Element, MouseEvent>) => setTab(e, "today")}
href="#today"
>
today
</Nav.Link>
</Nav.Item>
<NavDropdown
title={activeTab === "month" ? dateFormat(dateStart!, "MMMM yyyy") : "month"}
id="month"
>
{months.map((m) => (
<NavDropdown.Item onClick={() => setMonth(m)} key={dateFormat(m, "MMMM yyyy")}>
{dateFormat(m, "MMMM yyyy")}
</NavDropdown.Item>
))}
</NavDropdown>
I've modified the following parts to fix the tab navigation and month selection:
defaultActiveKey={activeTab}
to the Nav
component to activate the tab on loadNav.Link
added eventKey="today"
to have the key for the today tab set up properlyNavDropdown.Item
added active={m === month}
where m
is the iterator of the map (e.g. Jan 2021, Feb 2021 etc) and month is the selected month. This is needed so the selection in the drop-down is working.onClick
of the drop-down items added setMonth
& setTab
to update the state.NavDropdown
added active={activeTab === "month"}
so the tab navigation is correctly updating.I've also used moment.js to generate the month array and to format the months. Generation of the array is from this SO answer.
You can have a look at the code below or in this Codesandbox.
/*import moment from "moment";
import { useState } from "react";
import Nav from "react-bootstrap/Nav";
import NavDropdown from "react-bootstrap/NavDropdown";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";*/
const {useState} = React;
const {Nav, NavDropdown} = ReactBootstrap;
const MONTH_FORMAT_STR = "MMM yyyy";
const months = Array.apply(0, Array(12)).map(function (_, i) {
return moment().month(i).format(MONTH_FORMAT_STR);
});
const curMonth = moment().format(MONTH_FORMAT_STR);
function App() {
const [month, setMonth] = useState(curMonth);
const [activeTab, setTab] = useState(`month`);
const [dateStart, setStart] = useState(""); // not implemented yet
return (
<Nav variant="tabs" defaultActiveKey={activeTab}>
<Nav.Item>
<Nav.Link
eventKey="today"
onClick={() => {
setTab("today");
console.log("set month", curMonth);
setMonth(curMonth);
}}
href="#today"
>
today
</Nav.Link>
</Nav.Item>
<Nav.Item>
<NavDropdown
id="month"
active={activeTab === "month"}
title={moment().month(month).format("MMMM YYYY")}
>
{months.map((m) => (
<NavDropdown.Item
title={m}
eventKey={m}
active={m === month}
onClick={() => {
setMonth(m);
setTab("month");
}}
key={m}
>
{m}
</NavDropdown.Item>
))}
</NavDropdown>
</Nav.Item>
{activeTab} {month}
</Nav>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-bootstrap/1.5.2/react-bootstrap.min.js" integrity="sha512-Mw0NWa5M4d73pjqO5CY7Olq0yjPg80GsKCRHpy114idMaX8v+scJmRvhWbXTct8inkKGJNzBvMyWG4ok79zigQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"
integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l"
crossorigin="anonymous"
/>
<div id="root"/>