skip to Main Content

I have an open/close component that is applied to multiple sections.

export default function Expand() {
  const [open, setOpen] = useState(false);
  const expand = () => {
    setOpen(!open);
  };

Later in my code I have this (EDITED):

 {sections.map((item, i) => (
            <div key={i}>
              <button
                onClick={expand}>
                <h2>{item.heading}</h2>

And then:

{open && ( <div>Text when you open</div> ) }

Problem is that the multiple sections all open/close when clicking just one section. I need that when you click section one, only section one opens/closes. Then when clicking section two, only section two opens/closes.

I figure that I have to use this keyword but with my current code I don´t see where to add. Where to add to achieve my goal?

2

Answers


  1. this keyword is irrelevant here. You cannot use a single state value to keep track of expended state of multiple sections; you need an array of states.

    import React, { useState } from 'react';
    
    export function App(props) {
      const sections = ['s1', 's2', 's3'];
      const [isOpen, setIsOpen] = useState(Array(sections.length).fill(false));
    
      const toggleOpen = (index) => {
        const newIsOpen = [...isOpen];
        newIsOpen[index] = !newIsOpen[index];
        setIsOpen(newIsOpen);
      };
    
      return (
        <div className='App'>
          {sections.map((item, i) =>
            <div key={i}>
              <button onClick={() => toggleOpen(i)}>Toggle section {item}</button>
              {isOpen[i] && <div>{item}</div>}
            </div>)}
        </div>
      );
    }
    
    Login or Signup to reply.
  2. Create a custom hook useExpand like

    export default function useExpand() {
        const [isExpanded, setIsExpanded] = useState('closed');
        const expand = (sectionName)=>setIsExpanded(sectionName);
        return [isExpanded, expand];
    }
    // And the in the component use the hook:
    export function Component() {
        const [isExpanded, expand] = useExpand();
        // your code...
        {sections.map((item, i) => (
            <div key={i}>
                <button
                    onClick={expand(item.heading)}>
                    {item.heading}
                </button>
             </div>
             )}
    }
    // and finally to actually expand ...
    {isExpanded === item.heading && ( <div>Text when you open</div> )}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search