Search code examples
javascriptreactjsgithub-api

toggle a specific div tag in an array


I am building a simple ReactJS app to fetch GitHub user and display there repos. I am displaying the users in an array each have a details button, onClick only that specific users div tag must be displayed. I am able to pass username on click but onClick all users div tag are toggling. I want to display repos on clicking the details button.

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import _ from 'lodash';

class SearchResults extends Component {
  constructor(props) {
    super(props);
    this.state = { isOpen: false };
    this.toggleDetails = this.toggleDetails.bind(this);
  }

  toggleDetails(userName) {
    console.log(userName);

    this.setState({ isOpen: !this.state.isOpen });
  }

  render() {
    const { userList, userCount } = this.props;
    const {isOpen} = this.state;
    console.log('in searchResult = ' + this.props.userCount)

    if (userList) {
      var list = _.map(userList, (row, key) => {
        return (
          <div className="d-flex justify-content-center" key={row.id}
            style={{ border: '0px solid red' }}>
            <div className="card shadow-sm rounded" >
              <div className="card-body ">
                <div className="row ">
                  <div className="col-sm-2">
                    <img src={row.avatar_url} style={{ width: '80px', height: '80px' }}
                      className="rounded-circle" />
                  </div>
                  <div className="col-sm-10" style={{ border: '0px solid black' }}>
                    <h5 className="card-title">  {row.login}</h5>
                    <p className="display-6 text-muted"> {row.html_url} </p>
                    <button className="btn btn-outline-primary btn-sm float-right"
                      onClick={() => this.toggleDetails(row.login)}  >
                      Details
                    </button>
                  </div>
                </div>
              </div>
              {
                isOpen && 
                <table class="table table-striped" >
                  <tbody>
                    <tr>
                      <td>Otto</td>
                      <td>@mdo</td>
                    </tr>
                    <tr>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <td>the Bird</td>
                      <td>@twitter</td>
                    </tr>
                  </tbody>
                </table>
              }
            </div>
          </div>

        )
      })
    } else {
      var list = (
        <div className="d-flex justify-content-center ">
          <div className="card shadow-sm rounded" >
            <div className="card-body ">
              <div className="row ">
                No results to show
                </div>
            </div>
          </div>
        </div>
      )
    }

    return (
      <div className="user-list">
        {userList ?
          <div className="d-flex justify-content-center">
            <div className="count">
              <h6 className="display-6">Total Results :  {userCount} </h6>
            </div>
          </div> :
          <div className="d-flex justify-content-center">
            <div className="count">
              <h6 className="display-6">Total Results :  {userCount} </h6>
            </div>
          </div>
        }
        {list}
      </div>
    )
  }
}

export default SearchResults;

Solution

  • isOpen state is shared by all users. So you can try adding another state to keep the specific username which is open currently.

    import React, { Component } from 'react';
    import { Link } from 'react-router-dom';
    import _ from 'lodash';
    
    class SearchResults extends Component {
      constructor(props) {
        super(props);
        this.state = { isOpen: false, currentUser : '' };
        this.toggleDetails = this.toggleDetails.bind(this);
      }
    
      toggleDetails(userName) {
        console.log(userName);
        const currentUser = this.state.currentUser == userName ? '' : userName;
        this.setState({ isOpen: !this.state.isOpen, currentUser:userName  });
      }
    
      render() {
        const { userList, userCount } = this.props;
        const {isOpen, currentUser} = this.state;
        console.log('in searchResult = ' + this.props.userCount)
    
        if (userList) {
          var list = _.map(userList, (row, key) => {
            return (
              <div className="d-flex justify-content-center" key={row.id}
                style={{ border: '0px solid red' }}>
                <div className="card shadow-sm rounded" >
                  <div className="card-body ">
                    <div className="row ">
                      <div className="col-sm-2">
                        <img src={row.avatar_url} style={{ width: '80px', height: '80px' }}
                          className="rounded-circle" />
                      </div>
                      <div className="col-sm-10" style={{ border: '0px solid black' }}>
                        <h5 className="card-title">  {row.login}</h5>
                        <p className="display-6 text-muted"> {row.html_url} </p>
                        <button className="btn btn-outline-primary btn-sm float-right"
                          onClick={() => this.toggleDetails(row.login)}  >
                          Details
                        </button>
                      </div>
                    </div>
                  </div>
                  {
                    isOpen && currentUser === row.login &&
                    <table class="table table-striped" >
                      <tbody>
                        <tr>
                          <td>Otto</td>
                          <td>@mdo</td>
                        </tr>
                        <tr>
                          <td>Thornton</td>
                          <td>@fat</td>
                        </tr>
                        <tr>
                          <td>the Bird</td>
                          <td>@twitter</td>
                        </tr>
                      </tbody>
                    </table>
                  }
                </div>
              </div>
    
            )
          })
        } else {
          var list = (
            <div className="d-flex justify-content-center ">
              <div className="card shadow-sm rounded" >
                <div className="card-body ">
                  <div className="row ">
                    No results to show
                    </div>
                </div>
              </div>
            </div>
          )
        }
    
        return (
          <div className="user-list">
            {userList ?
              <div className="d-flex justify-content-center">
                <div className="count">
                  <h6 className="display-6">Total Results :  {userCount} </h6>
                </div>
              </div> :
              <div className="d-flex justify-content-center">
                <div className="count">
                  <h6 className="display-6">Total Results :  {userCount} </h6>
                </div>
              </div>
            }
            {list}
          </div>
        )
      }
    }
    
    export default SearchResults;