-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Description
Describe the bug
Hello! I looked for an existing issue and couldn't find so opening here.
I noticed a problem when trying to use myMutation.variables
as the value
prop in a textarea. My hope was that I could do that as a way to avoid synchronizing with a useState
while using the mutation to send updates to the server. More or less this:
export function MyComponent() {
const myMutation = useMutation({
mutationFn: async (params: {text: string}) => {
await new Promise(r => setTimeout(r, 500))
return params.text.split(',')
},
})
return <textarea
value={myMutation.variables?.text || ''}
onChange={ev => myMutation.mutate({text: ev.target.value})}
/>
}
This mostly works, but if you try to edit something at the beginning of the textarea, the cursor jumps to the end.
According to this blog this happens when the value
prop is updated asynchronously: https://dev.to/kwirke/solving-caret-jumping-in-react-inputs-36ic
I made a demo, along with a workaround which wraps the mutation and uses useState
to store a synchronous copy of variables
: - on the left, the cursor "jumps" to the end when you type at the start of the textarea.
Your minimal, reproducible example
https://v0.dev/chat/react-query-demo-ec5BxFS85Rs?f=1
Steps to reproduce
- Go to the link above
- Type stuff in both boxes
- Move the cursor to the start and keep typing. It jumps to the end on the left, but not on the right
Expected behavior
I'd expect the cursor not to jump around.
The following helper can wrap a mutation at make it work that way:
function useMutationWithLocalVariables<Mutation extends { mutate: (args: any) => void; variables: any }>(
mutation: Mutation,
): Mutation {
const { variables: _v, mutate: _m, ...rest } = mutation
const [variables, setVariables] = useState<typeof _v>()
const mutate = useCallback<typeof _m>(
mutateArgs => {
setVariables(mutateArgs)
return void _m(mutateArgs)
},
[_m, setVariables],
)
return { ...rest, mutate, variables } as Mutation
}
Usage
const myMutation = useMutationWithLocalVariables(useMutation(...))
How often does this bug happen?
Every time
Screenshots or Videos
No response
Platform
- any platform
Tanstack Query adapter
None
TanStack Query version
5.74.3
TypeScript version
5
Additional context
No response