Solution

To add active class dynamically in react js, use conditional rendering based on the condition we can able to toggle active class in the list.

In this article, we will create a clickable menu and when users click on any menu will show their sub-menu.

Snippet

In this snippet section, we will show those codes which are playing important role in this example.

Here, we are rendering menus dynamically from the array and if the array contains isActive - true then we are adding an active class for those menus.

{/* Rendering menus dynamically */}
{
  menus.map((menu) => (
    <div class="navigation">
      <a href="#" onClick={() => handleMenu(menu.id)}>
        {menu.name}
      </a>
      {/* Checking links array before rendering else code will crash if links are not present */}
      {menu.links && (
        // adding active class dynamically based on condition
        <div class={`navigation-content ${menu.isActive ? "active" : ""}`}>
          {menu.links.map((link) => (
            <a href={link.url}>{link.name}</a>
          ))}
        </div>
      )}
    </div>
  ));
}

Changing isActive Flag on click

We have created a function where we are making isActive - true and false based on the clicked menu.

/**
 * handleMenu
 *
 * In this function, we are doing isActive true for clicked menu and false for else.
 *
 * @param {*} menuId
 */
const handleMenu = (menuId) => {
  let menusData = [...menus];
  for (let menu of menusData) {
    if (menu.id === menuId) {
      menu.isActive = true;
    } else {
      menu.isActive = false;
    }
  }
  setMenus(menusData);
};

Example

Below is a full example version of adding an active class dynamically in react js.

Let’s start coding…

App.js

import React, { useState, useEffect } from "react";
import "./styles.css";

const menuList = [
  {
    id: 1,
    name: "Menu 1",
    links: [
      {
        name: "Link 1",
        url: "#",
      },
      {
        name: "Link 2",
        url: "#",
      },
      {
        name: "Link 3",
        url: "#",
      },
    ],
  },
  {
    id: 2,
    name: "Menu 2",
    links: [
      {
        name: "Link 1",
        url: "#",
      },
      {
        name: "Link 2",
        url: "#",
      },
      {
        name: "Link 3",
        url: "#",
      },
    ],
  },
  {
    id: 3,
    name: "Menu 3",
  },
];
export default function App() {
  const [menus, setMenus] = useState([]);

  useEffect(() => {
    //Expecting you will get this list from Api's that's why adding isActive false for each menu
    if (menuList && menuList.length > 0) {
      for (let menu of menuList) {
        menu.isActive = false;
      }
      setMenus(menuList);
    }
  }, []);

  /**
   * handleMenu
   *
   * In this function, we are doing isActive true for clicked menu and false for else.
   *
   * @param {*} menuId
   */
  const handleMenu = (menuId) => {
    let menusData = [...menus];
    for (let menu of menusData) {
      if (menu.id === menuId) {
        menu.isActive = true;
      } else {
        menu.isActive = false;
      }
    }
    setMenus(menusData);
  };

  return (
    <div className="App">
      <h1>React clickable menu example using CSS</h1>
      <div>
        {/* Rendering menus dynamically */}
        {menus.map((menu) => (
          <div class="navigation">
            <a href="#" onClick={() => handleMenu(menu.id)}>
              {menu.name}
            </a>
            {/* Checking links array before rendering else it code will crash if links are not present */}
            {menu.links && (
              // adding active class dynamically based on condition
              <div
                class={`navigation-content ${menu.isActive ? "active" : ""}`}
              >
                {menu.links.map((link) => (
                  <a href={link.url}>{link.name}</a>
                ))}
              </div>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

styles.css

.navigation {
  position: relative;
  display: inline-block;
}

.navigation-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  border-radius: 4px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
}

.navigation a {
  color: black;
  padding: 12px;
  margin: 0;
  text-decoration: none;
  display: block;
}

.navigation a:hover {
  background-color: #ddd;
  border-radius: 4px;
}

.navigation .active {
  display: block;
}

Output

dynamically, add, class

codesandbox