Home > Blockchain >  React Accordion opens and closes all elements
React Accordion opens and closes all elements

Time:02-01

when I click on the button all accordion elements are opened. how to make only clicked element to be opened. this is a react accordion app. I am not able to find the problem in the code.

import React, { useState } from "react";
//import {questions} from './api';

const questions = [
  {
    id: 1,
    question: "what is a",
    answer: "a is a"
  },
  {
    id: 2,
    question: "what is b",
    answer: "b is b"
  },
  {
    id: 3,
    question: "what is c",
    answer: "c is c"
  }
];

function Accordian() {
  const [toggle, settoggle] = useState(false);

  function mapfunc(currentValue) {
    return (
      <div key={currentValue.id} className="elements">
        <h3 className="question">
          {currentValue.question}
          <button
            onClick={function () {
              settoggle(!toggle);
            }}
            className="button"
          >
            {toggle ? "➖" : "➕"}
          </button>
        </h3>

        {toggle && <p className="answer"> {currentValue.answer} </p>}
      </div>
    );
  }

  return (
    <div>
      <h1>Accordian App</h1>
      {questions.map(mapfunc)}
    </div>
  );
}

export default Accordian;

CodePudding user response:

You need to move the toggle item with its logic to a separate component.

Item

import React, { useState } from "react";

const Item = ({ currentValue }) => {
  const [toggle, settoggle] = useState(false);

  return (
    <div key={currentValue.id} className="elements">
      <h3 className="question">
        {currentValue.question}
        <button
          onClick={function () {
            settoggle(!toggle);
          }}
          className="button"
        >
          {toggle ? "➖" : "➕"}
        </button>
      </h3>

      {toggle && <p className="answer"> {currentValue.answer} </p>}
    </div>
  );
};

Accordian

const questions = [
  {
    id: 1,
    question: "what is a",
    answer: "a is a"
  },
  {
    id: 2,
    question: "what is b",
    answer: "b is b"
  },
  {
    id: 3,
    question: "what is c",
    answer: "c is c"
  }
];

function Accordian() {
  return (
    <div>
      <h1>Accordian App</h1>
      {questions.map((item) => (
        <Item currentValue={item} />
      ))}
    </div>
  );
}

export default Accordian;

Edit eloquent-feather-gesmy

CodePudding user response:

The problem here, is that the state is at the Accordion level. So if it is true, all of the children of the Accordion will be opened. Instead, you should create a children component, that take as argument a question, and that has a local toggle state. You could instantiate it like this for instance:

return (
         <div>
            <h1>Accordian App</h1>
                {questions.map(question => <AccordionChildren question={question} />)}
        </div>
    )
  •  Tags:  
  • Related