`useFocusWithin` calls outdated `onFocus` and `onBlur` handlers
Dependencies check up
- [x] I have verified that I use latest version of all @mantine/* packages
What version of @mantine/* packages do you have in package.json?
8.3.9
What package has an issue?
@mantine/hooks
What framework do you use?
create-react-app (CRA)
In which browsers you can reproduce the issue?
All
Describe the bug
The useFocusWithin hook calls outdated callback handlers that capture stale state values from the initial render.
Reproduction
In the following code, the ref returned by useFocusWithin is attached to a form element:
import { useFocusWithin } from "@mantine/hooks";
import { useState } from "react";
function MyComponent() {
const [focusCount, setFocusCount] = useState(0);
const [blurCount, setBlurCount] = useState(0);
const { focused, ref } = useFocusWithin({
onFocus: () => {
console.log("focused!");
setFocusCount(focusCount + 1);
},
onBlur: () => {
console.log("blurred!");
setBlurCount(blurCount + 1);
},
});
return (
<div>
<p>focusCount = {focusCount}</p>
<p>blurCount = {blurCount}</p>
<p>focused = {focused ? "true" : "false"}</p>
<form ref={ref}>
<input type="text" placeholder="inside form" />
</form>
<button>outside form</button>
</div>
);
}
Expected behavior
When repeatedly moving focus between the input (inside the form) and the button (outside the form), the corresponding value of focusCount or blurCount should increment each time the focus changes.
Actual behavior
focusCount and blurCount never exceed 1, even though "focused!" and "blurred!" are logged to the console every time the focus changes.
This suggests that useFocusWithin continues to call the onFocus and onBlur handlers from the initial render, which captured the initial values of focusCount and blurCount (both 0).
If possible, include a link to a codesandbox with a minimal reproduction
https://codesandbox.io/p/devbox/mantine-react-template-forked-jccfsr
Possible fix
In the source code of useFocusWithin, there are places where previousNode.current is read, but it is never updated. Assigning previousNode.current = node within callbackRef may resolve this issue (though I haven't verified this yet).
Self-service
- [ ] I would be willing to implement a fix for this issue
Sure @hassanzadeh-mj you are welcome to submit a PR with a fix