1

i'm currently learning ReactJS, and im facing an issue while tryng to hide/show a div! The following code is working, but when i'm clicking the button "Learn More" it hide every description on every card, but i would like to show/hide the description only where i clicked it.

import Axios from 'axios';
import React, { useEffect, useState } from 'react';
import JobApplicationList from './JobApplicationList';
import Card from "react-bootstrap/Card";
import ScriptTag from 'react-script-tag';



export default class Home extends React.Component{
    
    constructor(){
        super()
        this.state={
            showMe:true,
            advLists: []
        }
    }

    operation(){
        this.setState({
            showMe:!this.state.showMe
        })
    }

    
    
      componentDidMount() {
        Axios.get(`http://localhost:3001/get/adv`)
          .then(res => {
            const advLists = res.data;
            
            this.setState({ advLists });
          })
      }

      

render(){
    

    return (
        
        <div className="main-page">
            <div className="adv_container">
                {this.state.advLists.map((val, key) => {
                    return (
                        <div className="card_">
                            <Card style={{ width: "100%" }}>
                                <Card.Body>
                                    <Card.Title>{val.compName}</Card.Title>
                                    <Card.Subtitle className="mb-2 text-muted">
                                    {val.city} | {val.compWebsite}
                                    </Card.Subtitle>
                                    <Card.Subtitle className="mb-2 text-muted">
                                    {val.salaire} €
                                    </Card.Subtitle>
                                    { this.state.showMe?
                                        <div className="description">
                                        <Card.Text>{val.description}</Card.Text>
                                        </div>
                                        :null
                                    }
                                    <Card.Link onClick={()=> this.operation()} id="toto" href="#">Learn more</Card.Link>
                                    <Card.Link href="#">Apply</Card.Link>
                                </Card.Body>
                                
                                
                            </Card>
                        </div>
                    );
                })}

            </div>
        </div>
    )
}
}


I kinda know what's going wrong, when i'm pressing the button i give the showMe state to every card, but i dont know how to fix it! Thanks in advance for the help.

2 Answers 2

1

Make the initial showMe state null and convert operation to take an index to toggle. If the index is already saved in state then set back to null.

operation(index) {
  this.setState({
    showMe: this.state.showMe === index ? null : index,
  })
}

Use the mapped index to pass to the handler and check this index against the showMe state to display the card.

{this.state.advLists.map((val, key) => {
  return (
    <div className="card_">
      <Card style={{ width: "100%" }}>
        <Card.Body>
          <Card.Title>{val.compName}</Card.Title>
          <Card.Subtitle className="mb-2 text-muted">
            {val.city} | {val.compWebsite}
          </Card.Subtitle>
          <Card.Subtitle className="mb-2 text-muted">
            {val.salaire} €
          </Card.Subtitle>
          {this.state.showMe === key && ( // <-- check if index/key matches
            <div className="description">
              <Card.Text>{val.description}</Card.Text>
            </div>
          )}
          <Card.Link
            onClick={() => this.operation(key)} // <-- pass key/index to toggle
            id="toto" href="#"
          >
            Learn more
          </Card.Link>
          <Card.Link href="#">Apply</Card.Link>
        </Card.Body>
      </Card>
    </div>
  );
})}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, so much this is working ! I was working with the id of the card , i was so close !
@AlexisDaCosta Right, using an id associated with the mapped element from your data would actually be preferred, but since I didn't see any property that looked like it was unique in the data set and I didn't see anything in your code that hinted that you would be adding/removing elements from this.state.advLists (i.e. the array length is static) using the index is a decent fallback.
1

I can give you the code pattern on how to toggle individual items using a React class component.

class MyComponent extends React.Component {
  state = { items: [] }; // initial state

  componentDidMount() {
    // fetched data
    this.setState({ items: [{ title: "one" }, { title: "two" }] }); 
  }

  toggleItem = (index) => {
    let items = this.state.items;
    items[index].hidden = !items[index].hidden; // mutating
    this.setState({ items }); // new object triggers re-render
  };

  render() {
    return (
      <ul>
        {this.state.items.map((item, index) => {
          return (
            <li key={index}> {/* remember to use a key */}
              <button onClick={() => this.toggleItem(index)}>toggle</button>

              {!item.hidden && item.title}
            </li>
          );
        })}
      </ul>
    );
  }
}

1 Comment

Thanks a lot i will probably use this for the future !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.