TanStackT
TanStack11mo ago
3 replies
continuing-aqua

Using component state values in useMutation.mutate (closure/race condition help)

Can someone help me understand why my payload is always an empty string in the code below?

I have a state variable that holds a user's comment which works fine.

When a button is pressed I call useMutation.mutate() and then reset the comment state. Inside the mutationFn the value of comment is always the reset state and it seems like the setState function executes before the mutationFn even if it's called afterward.

I know I can fix this by passing an argument to the mutationFn or resetting the state as part of an onSuccess callback. I know there's better practices than the code below. But what I really want is some help understanding why the comment is the reset value. Why does the mutation seem to execute after the state is updated?

const Feedback = () => {
  const [comment, setComment] = useState('');

  const postCommentMutation = useMutation({
    mutationFn: () => {
      const postComment = async () => {
        const payload = comment; // Why is this always an empty string?
        return await myApi.postComment(payload);
      };
      return postComment();
    },
  });

  return (
    <>
      <input value={comment} onChange={e => setComment(e.target.value)} />
      <button
        onClick={() => {
          postCommentMutation.mutate();
          setComment('');
        }}
      />
    </>
  );
};
Was this page helpful?