DEV Community

Alberto Cubeddu
Alberto Cubeddu

Posted on

Implementing Conditional Hover States in Nested Divs with React Hooks

In this article, we’ll simulate an interview scenario. We’ll begin by outlining a specific task and its requirements, and then delve into what a candidate should ideally think and consider during the interview to successfully navigate the situation.

The task

“Your task is to demonstrate how you would implement a hover effect for nested div elements in a React application. This will involve using React Hooks to manage the conditional behaviour of these elements based on their hover state.”

The image provided displays two rectangular panels that represent the transition of a hover effect:

  1. First Panel (“First Header”): Shows the default or initial visual state of the element before any mouse interaction.
  2. Second Panel (“Second Header”): Depicts the changed appearance of the element when the cursor hovers over it, indicating the hover state has been activated.

Requirements

  • You must use Tailwind CSS.
  • You can omit the arrow, however, pay attention to the underline.
  • Use React Hooks (e.g., useState, useEffect) to manage the hover state of the nested div elements.
  • Ensure that the hover state triggers a visual transition between the two states illustrated in the panels.
  • Your solution should accommodate the scenario where hovering over a nested div element triggers its specific hover effect without interfering with the parent or adjacent elements.
  • Your solution should provide a different way to achieve the same result; No code is needed.
  • Ensure you add anything extra you would like to consider if this is a real production application.

Start with the analysis

As a candidate, before jumping into technical details, confirm with the interviewer you’ve understood the task, and ensure you’re clarifying the requirements outlining the desired effect upon interaction with the element:

Example

Based on the task and requirements provided, my understanding is that when the mouse moves beyond the borders of the “rectangular panel,” we are required to:

  • Change the colour of the text for the “Header” and the “Explore”
  • Add an underline on the “Explore”
  • Transition the background from white (#FFF) to black (#000)
  • Ensure no other elements are changed.
  • We can omit the arrow to speed up the development and provide an MVP faster.

Continue explaining your reasoning

By reading the requirement I understand we must use React (as React hooks are mentioned) and Tailwind. To accomplish the result as requested by using Event Handlers we should start analysing the design, understand the interaction across the elements and finally find a way to communicate the changes.

Event Handlers: onMouseEnter and onMouseLeave

Utilising the onMouseEnter() and onMouseLeave(), we can detect when the mouse cursor enters or leaves the boundaries of the rectangular element a.k.a “The outer div”.

Using the return function in those two handlers allows us to send messages downstream to the inner elements, enabling us to apply the hover state where necessary. A straightforward approach would involve implementing a toggle switch that can be turned on or off, signalling the state change to the specific inner elements that need to be adjusted.

React Hooks: useState

Our end objective is to modify the visual state of an element in response to a user event (more specifically a mouseHandler event). By binding the event to the outer div, we can then use the return to understand when the mouse enters/leave the outside area. The last piece of the puzzle is the communication between the EventHandler and the other element(s) inside the component. We can useState specifically registering when the mouse is entering setIsHovered(true) and exiting setIsHovered(false)the desired area.

 interface CardProps {  
  headerText: string;  
  paragraphText: string;  
  backgroundColor: string;  
}  

const Card: React.FC<CardProps> = ({  
  headerText,  
  paragraphText,  
  backgroundColor,  
}) => {  
  const [isHovered, setIsHovered] = useState(false);  

  return (  
    <div  
      id="container"  
      className={containerClass}  
      style={dynamicStyle}  
      onMouseEnter={() => setIsHovered(true)}  
      onMouseLeave={() => setIsHovered(false)}  
    > </div>  
   )  
}
Enter fullscreen mode Exit fullscreen mode

Reading a state

Now we have our state changing in real-time, if we want to change any of the elements inside the component, we must read the state, and then automatically react will re-render the component based on the condition we specify.

In our example, we want to apply a conditional hover, and there is nothing simpler than using:

<span  
  className="flex self-center items-center flex-col"  
  style={{ textDecoration: isHovered ? "underline" : "none" }}  
>
Enter fullscreen mode Exit fullscreen mode

Different Alternatives

As mentioned at the beginning the problem can have different solutions; In software engineering, we work with trade-offs where we need to calculate the benefit of one solution against others. In this case, we’ve already a guideline simplifying the decision-making process, however, it’s important to outline some of the different ways.

Hover State with CSS — Descendant combinator

Using pure CSS we could avoid the use of hooks and eventHandler, as the :hover pseudo-classes and descent combinator

.outer:hover .inner {

background-color: lightblue; /* Changes when the outer div is hovered */

}

Hover over me!

I change color when the outer div is hovered over.  
Enter fullscreen mode Exit fullscreen mode

Hover State with CSS — Child combinator

Very similar to the solution above, however, we use a more direct specific relationship (parent-child)

.outer:hover > .inner {

background-color: lightblue; /* Changes when the outer div is hovered */

}

Production Deployment

I would ensure to provide enough metrics to the product team to understand if the functionality is beneficial to the final user and make data-driven decisions about future enhancements or modifications.

Conclusion

There is always a second way to achieve a result; It’s up to us to understand the context where we are and choose the best solution for the occasion.

Working solution: https://codesandbox.io/p/devbox/still-dream-ywpvwt.

Subscribe Today

If you found this content valuable, consider becoming a member to access exclusive insights like these. Subscribe Now to be the first to receive updates and emails about my latest work.

Follow me on LinkedIn

https://www.linkedin.com/in/alberto-cubeddu/ and suggest other articles you would like to see in this space!

Top comments (0)