Search code examples
reactjses6-map

reactjs array map method


i am trying to add a view more or view less section in the array map method , but when i use onclick method on a button inside the map method , all the buttons are acting instead of a specific one .

class Projects extends Component{
constructor(props){
super(props);
this.state={
  projects:[
    {
      id:1,
      title:'Calculator',
      description:'A Simple Javascript Calculator application'
    },
    {
      id:2,
      title:'ColorGuess',
      description:'A Javascript application'
    },
    {
      id:3,
      title:'GamesDB',
      description:'A React application',
    },
  ],
  clicked:false
  }
   this.toggle = this.toggle.bind(this)
 }

 toggle(){
  this.setState( state => ({
  clicked:!state.clicked
  }));
 }
render(){
  return(
   <div>
    <h2>My Projects</h2>
    <div className="d-flex flex-wrap justify-content-center">
    {
      this.state.projects.map( (project, i) =>{
        return(
          <div key={i} style={{width:'40%'}}>
            <div className="card">
              {project.title}
              <hr/>
              Description : {project.description} <br/>
              <button onClick={this.toggle}>
              {this.state.clicked ? <i class="fas fa-chevron-down"></i> : <i class="fas fa-chevron-up"></i>}
              </button>
            </div>
          </div>
        );
      })
     }
    </div>
   </div>
  );
 }
}

When i click on an individual button after rendering , but all the other buttons are acting as well instead of the specific one.

i have used arrow function and also passed the index along with , but still not working , Not Sure where it went wrong .


Solution

  • Instead of storing a boolean value for clicked, store the id of the clicked project and use that to toggle the state of button like

    class Projects extends React.Component{
      constructor(props){
        super(props);
          this.state={
            projects:[
              {
                id:1,
                title:'Calculator',
                description:'A Simple Javascript Calculator application'
              },
              {
                id:2,
                title:'ColorGuess',
                description:'A Javascript application'
              },
              {
                id:3,
                title:'GamesDB',
                description:'A React application',
              },
            ],
            clicked:false
          }
         this.toggle = this.toggle.bind(this)
       }
    
       toggle(id){
        this.setState( state => ({
          clicked: id === state.clicked? null: id
        }));
       }
       
       render(){
          return(
           <div>
            <h2>My Projects</h2>
            <div className="d-flex flex-wrap justify-content-center">
            {
              this.state.projects.map( (project, i) =>{
                return(
                  <div key={i} style={{width:'40%'}}>
                    <div className="card">
                      {project.title}
                      <hr/>
                      Description : {project.description} <br/>
                      <button type="button" onClick={() => this.toggle(project.id)}>
                      {this.state.clicked === project.id ? 'up' : 'down'}
                      </button>
                    </div>
                  </div>
                );
              })
             }
            </div>
           </div>
          );
        }
    }
    
    ReactDOM.render(<Projects />, document.getElementById('root'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script>
    <div id="root" />