Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open and Close a recursively nested list in React js

I'm looking to be able to open/close a nested list using React, so that when you click on the parent li the children are hidden? Here's what I used to create the list.

list.js

class List extends React.Component {

render(){
    return (
        <ul>
            {this.props.list.map(function(item){
                return (
                <li>
                    <ListItem key={item.id} item={item} />
                    <List list={item.children} />
                </li>
                );
            })}
        </ul>
    );
}

list-item.js

class ListItem extends React.Component {

handleCollapse(){
    console.log('Open/Close: ' + this.props.item.display_name);
    return false;
}

handleFilter(){
    console.log('Filter id: ' + this.props.item.id);
    return false;
}

render(){
    return (
        <div>
            <a rel="{this.props.item.id}" onClick={this.handleCollapse.bind(this)}>
                {this.props.item.display_name}  
            </a>
            <input value="" type="checkbox" onClick={this.handleFilter.bind(this)} />
        </div>
    )
}
like image 386
phenny19 Avatar asked Dec 22 '25 04:12

phenny19


1 Answers

Are you trying to simulate accordion behaviour? If yes then you can modify your code like this. Use component's state and toggle it to open and close children. Instead of creating <List list={item.children} /> in List class, import(or use require) list.js in list-item.js and render the child List item on the basis of current ListItem's state.

list-item.js

class ListItem extends React.Component {
  //Add this
  constructor (){
      super(...arguments);
      this.state = { showChild:false};
  }

  handleCollapse(){
      console.log('Open/Close: ' + this.props.item.display_name);
      //Add this
      this.setState({showChild:!this.state.showChild});
      return false;
  }

  handleFilter(){
      console.log('Filter id: ' + this.props.item.id);
      return false;
  }

  render(){
      let children;
      if(this.state.showChild) {
          children = (<List list={this.props.item.children} />);
      }

      return (
          <div>
              <a rel="{this.props.item.id}" onClick={this.handleCollapse.bind(this)}>
            {this.props.item.display_name}
              </a>
              <input value="" type="checkbox" onClick={this.handleFilter.bind(this)} />
             //Add this
             {children}
          </div>
      )
  };
}

list.js

class List extends React.Component {

    render(){
        //Removed <List .../>, rest is same just other way of doing same stuff
        let LI = this.props.list.map( (item) => {
            return( <li> <ListItem key={item.id} item={item} /></li>);
        }
     );

        return ( <ul>{LI}</ul>);
  }

};

dummy data to test

var data=[
  {
      id:"1st of Level 1",
      get display_name(){return _name(this.id,this.children)},
      children: [
          {
              id:"1st of Level 1.2",
              get display_name(){return _name(this.id,this.children)},
              children: [
                  {
                      id:"1st of Level 1.2.1",
                      get display_name(){return _name(this.id,this.children)},
                      children:[]
                  }
              ]
          },

          {
              id:"2nd of Level 1.2",
              get display_name(){return _name(this.id,this.children)},
              children:[]
          }
      ]
  },

  {
      id:"2nd of Level 1",
      get display_name(){return _name(this.id,this.children)},
      children:[]
  },

  {
      id:"3rd of Level 1",
      get display_name(){return _name(this.id,this.children)},
      children:[]
   },

   {
       id:"4th of Level1",
       get display_name(){return _name(this.id,this.children)},
       children:[]
   }

 ];

function _name(id,child) {
    if(child.length>0)
        return("I am "+id+" I HAVE CHILDREN");
    else {
        return("I am "+id+" I DON'T HAVE CHILDREN ");
    }    
}


ReactDOM.render(<List list={data} />,document.getElementById('root'));

`

like image 75
Udit Bhardwaj Avatar answered Dec 23 '25 17:12

Udit Bhardwaj