Busca en todas las páginas de la documentación
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
import { useState, useCallback, useMemo } from "react";
interface UseToggleReturn {
/** Valor booleano actual */
value: boolean;
/** Invierte el valor */
toggle: () => void;
/** Establece a true */
on: () => void;
/** Establece a false */
off: () => void;
/** Establece a un valor específico */
set: (value: boolean) => void;
}
function useToggle(initialValue: boolean = false): UseToggleReturn {
const [value, setValue] = useState(initialValue);
const toggle = useCallback(() => setValue((v) => !v), []);
const on = useCallback(() => setValue(true), []);
const off = useCallback(() => setValue(false), []);
return useMemo(
() => ({ value, toggle, on, off, set: setValue }),
[value, toggle, on, off]
);
}Cuándo usarlo: Tienes un estado booleano (modal abierto, sidebar visible, dark mode, feature flag) y quieres una API más limpia que useState crudo con alternancia de !prev dispersa en tu JSX.
"use client";
function Sidebar() {
const sidebar = useToggle(false);
return (
<div style={{ display: "flex" }}>
<aside
style={{
width: sidebar.value ? 250 : 0,
overflow: "hidden",
transition: "width 0.3s",
background: "#f5f5f5",
borderRight: "1px solid #e0e0e0",
}}
>
<nav style={{ padding: 16, whiteSpace: "nowrap" }}>
<ul style={{ listStyle: "none", padding: 0 }}>
<li>Panel de Control</li>
<li>Configuración</li>
<li>Perfil</li>
</ul>
</nav>
</aside>
<main style={{ flex: 1, padding: 16 }}>
<button onClick={sidebar.toggle}>
{sidebar.value ? "Cerrar" : "Abrir"} Sidebar
</button>
<p>Contenido principal aquí</p>
</main>
</div>
);
}
function DarkModeToggle() {
const darkMode = useToggle(false);
return (
<div
style={{
background: darkMode.value ? "#1a1a2e" : "#ffffff",
color: darkMode.value ? "#e0e0e0" : "#333",
padding: 24,
transition: "all 0.3s",
}}
>
<label style={{ display: "flex", alignItems: "center", gap: 8 }}>
<input
type="checkbox"
checked={darkMode.value}
onChange={darkMode.toggle}
/>
Modo Oscuro
</label>
</div>
);
}
function FeatureFlags() {
const betaFeature = useToggle(false);
const notifications = useToggle(true);
return (
<div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
<label>
<input
type="checkbox"
checked={betaFeature.value}
onChange={betaFeature.toggle}
/>
Características Beta
</label>
<label>
<input
type="checkbox"
checked={notifications.value}
onChange={notifications.toggle}
/>
Notificaciones
</label>
<div style={{ display: "flex", gap: 8 }}>
<button onClick={notifications.on}>Habilitar Todo</button>
<button onClick={notifications.off}>Deshabilitar Todo</button>
</div>
</div>
);
}Lo que esto demuestra:
sidebar.toggle reemplaza () => setOpen(!open) con una API más limpiadarkMode.value se lee naturalmente en expresiones de templatenotifications.on y notifications.off proporcionan llamadas explícitas para establecer verdadero/falsotoggle usa una actualización funcional (v) => !v para siempre invertir basándose en el valor actual, evitando problemas de cierre obsoleto.on y off establecen valores absolutos, útiles para botones de reinicio o manejadores de eventos que siempre deben establecer un state específico.useCallback memoiza todas las funciones para que sean referencialmente estables entre renderizados, seguras para pasar como props o usar en arrays de dependencias.useMemo envuelve el objeto de retorno para que los consumidores obtengan una referencia estable cuando solo se usan las funciones (que ya son estables).| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
initialValue | boolean | false | Valor inicial |
| Retorno | Tipo | Descripción |
|---|---|---|
value | boolean | State actual |
toggle | () => void | Invierte el valor |
on | () => void | Establece a true |
off | () => void | Establece a false |
set | (value: boolean) => void | Establece a cualquier booleano |
Retorno de tupla: Para una API más similar a useState, retorna una tupla:
function useToggle(initial = false): [boolean, () => void] {
const [value, setValue] = useState(initial);
const toggle = useCallback(() => setValue((v) => !v), []);
return [value, toggle];
}
// Uso
const [isOpen, toggleOpen] = useToggle();Con reducer: Para lógica de toggle compleja con historial de acciones:
function useToggle(initial = false) {
const [value, dispatch] = useReducer(
(state: boolean, action: "toggle" | "on" | "off") => {
switch (action) {
case "toggle": return !state;
case "on": return true;
case "off": return false;
}
},
initial
);
return { value, dispatch };
}Toggle persistente: Combina con useLocalStorage para toggles que sobreviven a la actualización:
function usePersistentToggle(key: string, initial = false) {
const [value, setValue] = useLocalStorage(key, initial);
const toggle = useCallback(() => setValue((v) => !v), [setValue]);
const on = useCallback(() => setValue(true), [setValue]);
const off = useCallback(() => setValue(false), [setValue]);
return { value, toggle, on, off };
}boolean.set acepta boolean directamente (no una unión con una función actualizadora) para mantener la API simple.useState(false) simple está bien. Solución: Recurre a useToggle cuando tengas múltiples toggles o quieras la API semántica on/off/toggle.useMemo, el objeto retornado crea una nueva referencia en cada renderizado, lo que puede causar re-renderizados innecesarios en los hijos. Solución: El useMemo en la receta maneja esto.useToggle para el state local de la UI, no para el state compartido.| Paquete | Nombre del Hook | Notas |
|---|---|---|
usehooks-ts | useToggle | Retorno de tupla [value, toggle] |
@uidotdev/usehooks | useToggle | Mínimo, retorno de tupla |
ahooks | useToggle | Admite toggle no booleano entre dos valores |
react-use | useToggle | Toggle booleano simple |
useToggle proporciona una API semántica: toggle(), on(), off() y set().!prev dispersa en JSX.toggle() invierte el valor actual a su opuesto.on() siempre establece el valor a true.off() siempre establece el valor a false.set(value) establece el valor a cualquier booleano que pases.Sin useMemo, se crea una nueva referencia de objeto en cada renderizado. Esto puede causar re-renderizados innecesarios en componentes hijos que reciben el objeto toggle como un prop. useMemo mantiene la referencia estable cuando solo se usan las funciones (ya memoizadas).
La actualización funcional lee el state actual en el momento de la ejecución, no en el momento en que se creó la función. Esto evita errores de cierre obsoleto cuando se llama a toggle() desde manejadores de eventos o efectos.
Sí. La sección Variaciones muestra una variante de tupla:
const [isOpen, toggleOpen] = useToggle();Usa la tupla para casos simples y el objeto para múltiples controles (on, off, set).
Combina con useLocalStorage:
function usePersistentToggle(key: string, initial = false) {
const [value, setValue] = useLocalStorage(key, initial);
const toggle = useCallback(() => setValue((v) => !v), [setValue]);
return { value, toggle };
}Si destructuras y recreas el objeto en el padre, la referencia cambia. Pasa el objeto envuelto en useMemo directamente, o pasa funciones estables individuales (toggle, on, off) como props separados.
No. useToggle es dueño de su propio state (no controlado). Si el padre necesita controlar el valor, pasa el booleano como un prop y usa callbacks. Usa useToggle solo para el state local de la UI.
Retorna UseToggleReturn, una interfaz con value: boolean, toggle: () => void, on: () => void, off: () => void y set: (value: boolean) => void. No se necesitan genéricos.
Sí. La sección Variaciones muestra una variante basada en reducer que despacha acciones de cadena como "toggle", "on" y "off". Esto es útil para lógica de toggle compleja o seguimiento del historial de acciones.
Revisado por Chris St. John·Última actualización: 16 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥