Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I bind a toggle to the clicked element to mapped data in react

I'm using reactstrap/bootstrap for an accordion functionality. I'm having trouble with my toggling and onclick. My state, function and render look like the following:

state = {
    basicFeatures: [],
    fuelEconomy: {},
    upholsteryType: null,
    category: 'Engine',
    collapse: false,
    active: false,
    activeTab: 'capabilities',
};


toggle = active =>
    this.setState({
        collapse: !this.state.collapse,
        active: !this.state.active,
    });

const specsCatsR = this.props.specs.map((item, i) => {
        return (
            <React.Fragment>
                <Col xs="12" key={i} className="border-bottom p-15">
                    <FontAwesomeIcon
                            icon={
                                this.state.active ? faMinusCircle : faPlusCircle
                            }
                        />
                        <h5 
                            className="collapse-header" 
                            onClick={this.toggle.bind(this)}
                            >
                            {' '}
                            {item.category}{' '}
                        </h5>
                        <Collapse isOpen={this.state.active}>
                            <SpecsDetails
                                vehicle={this.props.vehicle}
                                values={item.values}
                                category={item.category}
                            />
                        </Collapse>
                    </Col>
            </React.Fragment>
        );
    });

It spits out a list of items. However, when I click on one item, they all open/toggle. How can I bind it to only open the one that is clicked?

like image 413
Lz430 Avatar asked Dec 06 '25 03:12

Lz430


1 Answers

If only one of your elements is supposed to be expanded at a time, I recommend storing the id of the currently expanded item in your state (here in active).
The toggle function will receive the id of the clicked element and then the onClick event arguments by preconfiguring it :

state = {
    basicFeatures: [],
    fuelEconomy: {},
    upholsteryType: null,
    category: 'Engine',
    collapse: false,
    active: null, //Active is not a boolean anymore
    activeTab: 'capabilities',
};


toggle = id => ev => { //Add brackets here, you do not need to return the result of setState
    this.setState({
        collapse: !this.state.collapse,
        active: id,
    });
}

const specsCatsR = this.props.specs.map((item, i) => 
        <React.Fragment>
            <Col xs="12" key={i} className="border-bottom p-15">
                <FontAwesomeIcon
                    icon={
                        this.state.active ? faMinusCircle : faPlusCircle
                    }
                />
                <h5
                    className="collapse-header"
                    onClick={this.toggle(i)} // bind is not necessary since you are using an arrow function
                >
                    {` ${item.category} `}
                </h5>
                <Collapse isOpen={this.state.active === i}> //If the index is the same as the active element id, it expands
                    <SpecsDetails
                        vehicle={this.props.vehicle}
                        values={item.values}
                        category={item.category}
                    />
                </Collapse>
            </Col>
        </React.Fragment>
    );
like image 159
Treycos Avatar answered Dec 08 '25 17:12

Treycos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!