Home > front end >  React change icon onClick from loop
React change icon onClick from loop

Time:11-25

I included an Icon while mapping an array and I need to change the icon on that specific iteration on when clicked, I also want to render the test results when the icon is clicked.

I'm not sure how to get a unique value that is specific to this iteration that will handle this change or I've my structure is all wrong how should I handle this?

const Students = ({students}) => {

return (
    {students.map((student, i) => (
        <div className="wrapper" key={student.id}>
          <div className="img-container">
            <img src={student.pic} alt="student" />
          </div>
          <div className="content">
            <h1>
              {student.firstName.toUpperCase()} {student.lastName.toUpperCase()}
            </h1>
            <p>Email: {student.email}</p>
            <p>Company: {student.company}</p>
            <p>Skill: {student.skill}</p>
            <p>Average: {averageGrade(student.grades)}%</p>

            {faMinus && <TestResults results={student.tests} />}
          </div>
          <FontAwesomeIcon
            id={i}
            onClick={e => handleTests(e.target.id)}
            className="faIcon"
            icon={current ? faPlus : faMinus}
          />
        </div>
      ))}
  )
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Thanks ahead of time for any suggestions

CodePudding user response:

The return must always have a top-level tag.

  const Students = ({ students }) => {
    return (
      <>
        {students.map((student, i) => (
          <div className="wrapper" key={student.id}>
            <div className="img-container">
              <img src={student.pic} alt="student" />
            </div>
            <div className="content">
              <h1>
                {student.firstName.toUpperCase()}{" "}
                {student.lastName.toUpperCase()}
              </h1>
              <p>Email: {student.email}</p>
              <p>Company: {student.company}</p>
              <p>Skill: {student.skill}</p>
              <p>Average: {averageGrade(student.grades)}%</p>

              {faMinus && <TestResults results={student.tests} />}
            </div>
            <FontAwesomeIcon
              id={i}
              onClick={(e) => handleTests(e.target.id)}
              className="faIcon"
              icon={current ? faPlus : faMinus}
            />
          </div>
        ))}
      </>
    );
  };

CodePudding user response:

Let me know if this is what you're thinking. Just store the index in a state variable and compare against it. When they click change the index to the one they clicked on.

const Students = ({students}) => {
const [selectedIndex, setSelectedIndex] = useState(0)


function handleTests(id, index) {   //NEW
    //Your current code
    setSelectedIndex(index)   //NEW
}

return (
{students.map((student, i) => (
    <div className="wrapper" key={student.id}>
      <div className="img-container">
        <img src={student.pic} alt="student" />
      </div>
      <div className="content">
        <h1>
          {student.firstName.toUpperCase()} {student.lastName.toUpperCase()}
        </h1>
        <p>Email: {student.email}</p>
        <p>Company: {student.company}</p>
        <p>Skill: {student.skill}</p>
        <p>Average: {averageGrade(student.grades)}%</p>

        {selectedIndex == i && <TestResults results={student.tests} />}   //NEW
      </div>
      <FontAwesomeIcon
        id={i}
        onClick={e => handleTests(e.target.id, i)}   //NEW
        className="faIcon"
        icon={selectedIndex == i ? faPlus : faMinus}
      />
    </div>
  ))}
  )
}
  • Related