This week I had to implement some onHover behavior for a component but wanted to make it reusable and not have it as part of my component's state.
I have only been developing with React full time for the last 6 months so was struggling to come up with a clean way to do this.
Luckily I also started watching @kentcdodds's Advanced React Patterns where he explains how you can achieve this using render props.
So I implemented Hoverable
with a render prop (children). I can then pass it my existing component which takes in a prop hovered
and I can easily reuse it for other components.
Below is an example of how I implemented. You can also find it in this CodeSandbox
With Typescript I wasn't able to use children
as the prop so I used a render
prop... literally! You can see that in this CodeSandbox
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class Hoverable extends React.Component {
state = { hovered: false };
render() {
return (
<div
onMouseEnter={() => this.setState({ hovered: true })}
onMouseLeave={() => this.setState({ hovered: false })}
>
{this.props.children(this.state.hovered)}
</div>
);
}
}
function App() {
return (
<Hoverable>
{hovered => <div>{hovered ? "๐ฅ" : "๐ฆ"}</div>}
</Hoverable>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Top comments (8)
With typescript you could change the definition of the children prop type, or cast props to any before accessing children.
I would suggest to move the mouseEnter and Leave call backs to properties of the class so that you dont re create the functions every render pass
Thanks for the tips!
For the ts children definition - what would it look like? The code below still complains that children is not a function. CodeSandbox
Actually once I updated the usage to use children there's no longer errors.
That's awesome! thanks!
Sure, no worries.
I think the more correct would be:
children: (hovered: boolean) => void
As this implies a property with function signature instead of a method.
What is the difference between having it as a method or a property with function signature?
I have the same implementation.
And I encounter many issues whenever you are going super fast between many elements. It's like the state gets lost, and I saw that going that fast, many onMouseEnter / onMouseLeave gets forgotten, so the hovered state stays even if you are elsewhere...
Do you have tried that ?
Best emojis to use for the hover effect.
Burning ๐ฅ a ๐ฆ on hover :)
Ah! Did not mean for to be so brutal!