7279

How do I share data between repeated elements in React?

Question:

So I'm trying to create an expandable card component using React. I've set it up as below. It all works right now, I can tap on a card to expand it, and tap on it again to collapse it. Each card has its own state variable 'expanded'

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 one is open and you tap on another one, the first must close.

I've tried having a global 'expanded' variable to handle this, but the state variables are not two-way bound (as in Angular), so I can't change the value of one card's state from another one.

Can someone help? Thanks.

Answer1:

<strong>SOLUTION</strong>: Let the parent component handle all expanded states.

<strong>HOW?</strong> Save an expanded state foreach item in your parent component (CardList). You can save the states in an separate array with the same length as repeatEntity and map them, for example with the index to 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. Next you have to implement a callback function that takes the neccessary information to identify the toggled entity, as parameter. This would be the index or the entity object itself. Then, the callback function can change the matching expanded state of the passed 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 least you have to pass the callback and index to all items.

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); }

<strong>NOTE</strong>: Maybe there are some syntactical or semantical errors. Nevertheless, the approach should solve your problem.

Recommend

  • How to use PagedList on search results page in MVC?
  • Difference between returning ModelAndView in ajax call
  • Cannot connect to my database from within SQL Management Studio
  • React textarea with value is readonly but need to be updated
  • Javascript syntax null : ?{}
  • How can I reset dropdown data if modal closed on vue component?
  • Undefined navigator.push React-native 0.43.4
  • C: Incompatible pointer type initializing
  • why xml file does not aligned properly after append the string in beginning and end of the file usin
  • FileReader+canvas image loading problem
  • PHPUnit_Framework_TestCase class is not available. Fix… - Makegood , Eclipse
  • Insert into database using onclick function
  • Deselecting radio buttons while keeping the View Model in synch
  • Why HTML5 Canvas with a larger size stretch a drawn line?
  • How to add a column to a Pandas dataframe made of arrays of the n-preceding values of another column
  • script to move all files from one location to another location
  • Weird JavaScript statement, what does it mean?
  • Rearranging Cells in UITableView Bug & Saving Changes
  • How to delete a row from a dynamic generate table using jquery?
  • Python: how to group similar lists together in a list of lists?
  • Rails 2: use form_for to build a form covering multiple objects of the same class
  • Codeigniter doesn't let me update entry, because some fields must be unique
  • Proper way to use connect-multiparty with express.js?
  • Free memory of cv::Mat loaded using FileStorage API
  • Trying to get generic when generic is not available
  • Getting Messege Twice Using IMvxMessenger
  • Change div Background jquery
  • How to get Windows thread pool to call class member function?
  • Bitwise OR returns boolean when one of operands is nil
  • XCode 8, some methods disappeared ? ex: layoutAttributesClass() -> AnyClass
  • Easiest way to encapsulate a HTML5 webpage into an android app?
  • Django query for large number of relationships
  • Busy indicator not showing up in wpf window [duplicate]
  • Running Map reduces the dimensions of the matrices
  • costura.fody for a dll that references another dll
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Android Heatmap on canvas or ImageView
  • Conditional In-Line CSS for IE and Others?