paul.kim1901
paul.kim1901

Reputation: 461

How to.close accordion when clicked for the second time?



import React, { useState } from 'react';

const Accordion = ({ items }) => {
    const [activeIndex, setActiveIndex] = useState(null);

    const onTitleClick = (index) => {
        setActiveIndex(index);
    };

    const renderedItems = items.map((item, index) => {
        const active = index === activeIndex ? 'active' : '';

        return (
            <React.Fragment key={item.title}>
                <div className={`title ${active}`} onClick={() => onTitleClick(index)}>
                    <i className='dropdown icon'></i>
                    {item.title}
                </div>
                <div className={`content ${active}`}>
                    <p>{item.content}</p>
                </div>
            </React.Fragment>
        );
    });
    return <div className='ui styled accordion'>{renderedItems}</div>;
};

export default Accordion;

I created an accordion using Semantic UI library. I was able to set class of dropdown "active" so anything that I click will expand.

I am trying to implement "Close on second click" functionality to the below code, so I try to implement by adding following code under onTitleClick function:

    const onTitleClick = (index) => {
        if (index === activeIndex) {
            setActiveIndex(null); // in case 'clicked index' is the same as what's active, then configure it to "null" and rerender 
        }
        setActiveIndex(index);
    };

My understanding is whenever the state updates, react will run its script again, so in this particular situation, that variable "active" should return empty string if clicked for the same Index.

Rather than my expectation, nothing happened when I clicked it for the second time.

I tried to console.log in the if statement and it will show that I have clicked the item for the second time.

Please advise.

Upvotes: 1

Views: 1747

Answers (3)

Sudarshan bairagi
Sudarshan bairagi

Reputation: 1

I have tried with react class component so worked it.

import React, { Component } from 'react';

class Accordion extends Component {
  state = {
    activeIndex: null
  }
  onTitleClick = (index) => event => {
    const { activeIndex } = this.state;
    this.setState({ activeIndex: activeIndex == index ? null : index })
  };


  render() {
    const { activeIndex } = this.state;
    const{items}=this.props;
    return <div className='ui styled accordion'>
      {
        items.map((item, index) => {
          const active = index === activeIndex ? 'active' : '';
          return <React.Fragment key={item.title}>
            <div className={`title ${active}`} onClick={this.onTitleClick(index)}>
              <i className='dropdown icon'></i>
              {item.title}
            </div>
            <div className={`content ${active}`}>
              <p>{item.content}</p>
            </div>
          </React.Fragment>
        })
      }
    </div>
  }
}

export default Accordion;

Upvotes: 0

Sarun UK
Sarun UK

Reputation: 6736

Try the below approach,

 const onTitleClick = (index) => {
      setActiveIndex(activeIndex !== index ? index : null);
  };

Upvotes: 0

Shubham Verma
Shubham Verma

Reputation: 5054

The issue is here:

const onTitleClick = (index) => {
        if (index === activeIndex) {
            setActiveIndex(null); // in case 'clicked index' is the same as what's active, then configure it to "null" and rerender 
        }
        setActiveIndex(index); <-- here
    }

what happening here is if if condition matches then it sets to setActiveIndex null but code will run so again it sets to setActiveIndex(index). That's why click is not working . You need to do this:

 const onTitleClick = (index) => {
    if (activeIndex === index) {
      setActiveIndex(null);
    } else {
      setActiveIndex(index);
    }
  };

Here is the demo: https://codesandbox.io/s/musing-poitras-bkiwh?file=/src/App.js:270-418

Upvotes: 3

Related Questions