Snippet

useMousePosition

js

For certain interactions, you need to know exactly where the user's cursor is.

For example, on this blog, I have a “like” button which responds to the user's cursor position:

useMousePosition is a low-level hook used in effects like these. It measures the user's current mouse position, in pixels, from the top/left corner. It stores this data in React state, and updates it whenever the cursor moves.

Because it's held in React state, the component will re-render whenever the user moves the mouse, and so you can safely use it to calculate things like CSS transform values, canvas animations, etc.

Link to this heading
Example usage:

Code Playground

JSX

Result

Enable ‘tab’ key

This component will re-render whenever the user moves the mouse. This can be dozens and dozens of times a second.

Originally, this hook included “throttle” functionality, which would limit the updates to a user-specified interval. In testing, though, it seemed to make performance worse. No matter how hard I tried, I couldn't come up with a contrived scenario where the throttle actually improved performance (while still updating often enough for smooth animations).

That said, you do still need to be a bit careful where you use this hook. It shouldn't be used in a top-level component like App or Homepage, since that will cause a huge chunk of your React tree to re-render very often. Use this hook in the small “leaf node” components near the bottom of the tree.

For maximum performance, you can use a library like React Spring or Framer Motion, which will allow you to update values without triggering React renders. In my experience, though, as long as you're using this hook on smaller components that don't have a big DOM impact, you should be just fine.

If you're going to be using this hook to animate an element's position, be sure to consider the user's motion preferences!

You can check with the use-prefers-reduced-motion hook. For example:

js

Link to this heading
Touchscreens and mobile

This hook is written to respond exclusively to mouse events. This means that it'll ignore the movement of fingers across a touchscreen.

In my experience, I generally don't want to handle touch events in the same way. Dragging a finger across the screen is more like scrolling than it is like moving a mouse.

I mainly use this hook for cosmetic desktop-only effects, like the 404 error page on this blog.

For those curious, though, here's how I'd write this hook if it needed to also track touch position:

js