react Intermediate

React toggles hook

React toggles hook

Introduction

Managing visibility state for multiple dialogs, modals, and popups in a component can get repetitive fast. Each one needs its own useState, open handler, and close handler. The useToggles custom hook solves this by managing multiple toggle states with a single, clean API.

React Toggles Hook

Open this example in our interactive code editor to experiment with it.

Try the Editor

useToggles hook

import { useState } from "react";

const useToggles = (initialToggles = {}) => {
  const [toggles, setToggles] = useState(initialToggles);

  const open = (name) =>
    setToggles((prev) => ({ ...prev, [name]: true }));

  const close = (name) =>
    setToggles((prev) => ({ ...prev, [name]: false }));

  const toggle = (name) =>
    setToggles((prev) => ({ ...prev, [name]: !prev[name] }));

  const isOpen = (name) => !!toggles[name];

  return { open, close, toggle, isOpen };
};

export default useToggles;
  • useToggles accepts an initialToggles object where keys are toggle names and values are booleans (e.g., { dialog1: false, dialog2: false }).
  • open, close, and toggle update a specific toggle by name using the spread operator to preserve other toggle states.
  • isOpen returns the boolean state for a given toggle name, with !! to ensure it always returns a boolean.

App - 2 dialogs

import useToggles from "./useToggles";

export default function App() {
  const { open, close, isOpen } = useToggles({
    confirmDialog: false,
    settingsDialog: false,
  });

  return (
    <div>
      <button onClick={() => open("confirmDialog")}>Open Confirm</button>
      <button onClick={() => open("settingsDialog")}>Open Settings</button>

      {isOpen("confirmDialog") && (
        <div className="dialog">
          <p>Are you sure?</p>
          <button onClick={() => close("confirmDialog")}>Close</button>
        </div>
      )}

      {isOpen("settingsDialog") && (
        <div className="dialog">
          <p>Settings panel</p>
          <button onClick={() => close("settingsDialog")}>Close</button>
        </div>
      )}
    </div>
  );
}
  • The App component initializes two toggles: confirmDialog and settingsDialog, both starting as false.
  • Each dialog is conditionally rendered based on isOpen("dialogName").
  • open and close are called with the toggle name to show and hide each dialog independently.

Summary

  • useToggles eliminates repetitive useState calls by managing multiple boolean states in a single object.
  • The hook provides a clean API with open, close, toggle, and isOpen functions, all driven by string-based toggle names.
  • This pattern scales well as you add more dialogs, modals, dropdowns, or any UI element that needs show/hide logic.
  • It keeps your components clean and focused on rendering, while the hook handles all the state management.

Try this in our interactive code editor

Practice hands-on with our built-in code sandbox.

Open Code Editor
Adrian Bigaj
Adrian Bigaj

Creator of BigDevSoon

Full-stack developer and educator passionate about helping developers build real-world skills through hands-on projects. Creator of BigDevSoon, a vibe coding platform with 21 projects, 100 coding challenges, 40+ practice problems, and Merlin AI.