someonewithakeyboardz1
someonewithakeyboardz1

Reputation: 167

Display element for one person on hover

I am rendering a list of students, some of which have failed their exams. For those who have failed their exams, I display a red square behind their avatars.

Whenever I hover over a student's avatar I want to display the subject that student has failed. My issue at the moment is that I display the subjects for all students, not only the one I've hovered over.

How can I display only the mainSubject for the student who's avatar I hovered on?

Here is a link to my code sandbox: Example Link

Upvotes: 1

Views: 167

Answers (2)

Rajesh
Rajesh

Reputation: 24925

Issue is that you have a list of students but only 1 flag to show/hide subjects.

Solution: 1

Maintain a list of flag/student. So you will have n flags for n students. Simple way for this is to have a state in a way:

IStudentDetails { ... }
IStudentStateMap {
  id: string; // uniquely identify a syudent
  isSubjectVisible: boolean;
}

And based on this flag isSubjectVisible toggle visibility.

Updated code


Solution 2:

Instead of handling it using React, use CSS tricks. Note this is a patch and can be avoided.

Idea:

  • Wrap Student in a container element and add a class onHover on elements on elements that needs to be shown on hover.
  • Then use CSS to show/hide those elements.
.student-container .onHover {
  display:none;
}
.student-container:hover .onHover{
  display: block;
}

This way there wont be rerenders and no need for flags.

Updated Code


However, solution 1 is better as you have more control and when you are using a UI library, its better to let it do all mutation and you should follow its ways.

Upvotes: 1

Prince Sodhi
Prince Sodhi

Reputation: 2955

I solved it like following.

  • Get the id of the hovered student. Match this id from the list of students you render. if its match then show the subjects
  • Also, I renamed the hook
  • add key prop

you can check this too https://codesandbox.io/s/zealous-bhaskara-mi83k

    const [hoveredStudentId, setHoveredStudentId] = useState();

  return (
    <>
      {students.map((student, i) => {
        return (
          <div className="student-card" key={i}>
            <p>
              {student.firstName} {student.lastName}
            </p>
            {student.passed === false ? (
              <>
                <img
                  id={student.id}
                  src={student.picture}
                  className="student-avatar fail"
                  onMouseEnter={e => {
                    setHoveredStudentId(e.currentTarget.id);
                  }}
                  onMouseLeave={e => {
                    console.log(e.currentTarget.id);
                    setHoveredStudentId(0);
                  }}
                  alt="avatar"
                />
                {hoveredStudentId === student.id && (
                  <div className="subject-label">{student.mainSubject}</div>
                )}
              </>
            ) : (
              <img
                src={student.picture}
                className="student-avatar"
                alt="avatar"
              />
            )}
          </div>
        );
      })}
    </>
  );

Upvotes: 3

Related Questions