How can I share data between repeating elements in React?

So, I'm trying to create an extensible map component using React. I installed it as shown below. Everything is working now, I can click on the map to expand it and click on it again to collapse it. Each card has its own "advanced" state variable

var ExpandableListItem = React.createClass({
toggleCard: function(){
    var self = this
    this.setState({
        expanded: !self.state.expanded
    })
},

getInitialState: function(){
    return {
        expanded: false
    }
},

render: function(){
    return (
        <Card onTouchTap={this.toggleCard}>
            <CardText>
                {this.state.expanded ? 'Expanded Card' : 'Normal Card'}
            </CardText>
        </Card>
    )
}
})

var CardList = React.createClass({
render: function(){
    return (
        <div>
            {this.props.repeatEntity.map(function(element, index) {
                return (
                    <ExpandableListItem text={element[index].week}></ExpandableListItem>
                )}
            )}
        </div>
    )
}
})

      

What I want to have is only one card open at a time, that is, if it is open and you press another, the first one should close.

I tried to use a global variable with an extension, but the state variables are not two-way (like in Angular), so I cannot change the state value of one card from another one.

Can anyone please help? Thank.

0


source to share


1 answer


SOLUTION . Let the parent component handle all extended states.

AS? Store the expanded

state foreach element in its parent component ( CardList

). You can store states in a separate array with the same length as repeatEntity

and map them to, for example, the index for the correct entity.

array = [true, false, false]; // [0. expanded state, 1. ..., 2. ...]
entities = [{...}, {...}, {...}]; // [0. entity, 1. ..., 2. ...]

      

Alternatively, you can add a variable expanded

to each entity

. Then you need to implement a callback function that takes the information you need to identify the toggled parameter entity

as a parameter. This will be the index or the object itself entity

. The callback function can then change the consistent state of the expanded

past entity

.



handleCardItemToggle(entityIndex) {
    const expandedStates = this.state.entityStates;

    // set all values to 'false'

    expandedStates[entityIndex] = !expandedStates[entityIndex]; // toggle expanded-state of item

    this.setState({
        entityStates: expandedStates
    });
}

      

At the very least, you need to pass a callback and an index to all elements.

render: function(){
    return (
        <div>
            {this.props.repeatEntity.map(function(element, index) {
                return (
                    <ExpandableListItem id={index} isExpanded={this.state.entityStates[index]} handleToggle={this.handleCardItemToggle} text={element[index].week}></ExpandableListItem>
                )}
            )}
        </div>
    )
}


// in ExpandableListItem
toggleCard() {
    this.props.handleToggle(this.props.id);
}

      

NOTE . There may be syntax or semantic errors. However, this approach should solve your problem.

+1


source







All Articles