Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

200
Vistas
Toggle one list item at a time with React/TS functional components

I have a simple component with a few nested bits of mark-up:

    import React, { ReactElement } from "react";

    type MenuItem = {
        title: string;
        subItems?: Array<string>;
    };

    type MenuConfig = Array<MenuItem>;

    function Item({ item }: { item: MenuItem }): ReactElement {
        const [showItem, setShowItem] = React.useState(false);
        const handleShowItem = (): void => {
            setShowItem(!showItem);
        };
        return (
            <>
                {item.subItems && (
                    <button onClick={() => handleShowItem()}>
                        {showItem ? "Hide" : "Expand"}
                    </button>
                )}
                {showItem && <SubItem item={item} />}
            </>
        );
    }

    function SubItem({ item }: { item: MenuItem }): ReactElement {
        const { title } = item;
        return (
            <ul>
                {item?.subItems?.map((subitem: string, i: number) => (
                    <li key={i}>
                        {subitem}
                    </li>
                ))}
            </ul>
        );
    }

    function Solution({ menuConfig }: { menuConfig: MenuConfig }): ReactElement {
        return (
            <>
                {menuConfig.map((item: MenuItem, i: number) => (
                    <div key={i}>
                        <span>{item.title}</span>
                        <Item item={item} />
                    </div>
                ))}
            </>
        );
    }

    export default Solution;

This is what I am passing in:

menuConfig={[
                {
                    title: "About",
                },
                {
                    title: "Prices",
                    subItems: ["Hosting", "Services"],
                },
                {
                    title: "Contact",
                    subItems: ["Email", "Mobile"],
                },
            ]}

Now, it functions as expected, if an item contains subItems then an Expand button will be show which, if clicked, will only expand the relevant list.

How should I go about making sure only one list would be open at a time, given my implementation?

So if the user clicks Expand on a button, the other previously expanded lists should close.

I can't mess with the data that's coming in, so can't add ids to the object, but titles are unique.

I've searched and whilst there are a few examples, they don't help me, I just can't wrap my head around this.

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

This is a perfect use case for React context. You essentially want a shared state among your menu. You can achieve this with prop drilling however contexts are a much cleaner solution.

Code sandbox

const MenuContext = createContext<{
  expandedState?: [number, React.Dispatch<React.SetStateAction<number>>];
}>({});
function Solution(): ReactElement {
  const expandedState = useState<number>(null);
  const value = { expandedState };
  return (
    <>
      <MenuContext.Provider value={value}>
        {menuConfig.map((item: MenuItem, i: number) => (
          <div key={i}>
            <span>{item.title}</span>
            <Item i={i} item={item} />
          </div>
        ))}
      </MenuContext.Provider>
    </>
  );
}
function Item({ item, i }: { item: MenuItem; i: number }): ReactElement {
  const [expanded, setExpanded] = useContext(MenuContext)?.expandedState ?? [];
  const shown = expanded === i;
  return (
    <>
      {item.subItems && (
        <button onClick={() => setExpanded?.(i)}>
          {shown ? "Hide" : "Expand"}
        </button>
      )}
      {shown && <SubItem item={item} />}
    </>
  );
}
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda