18

I have two API calls in onVerificationCodeSubmit that covering reset password logic. The problem is that newPasswordMutation executes before setRestorePasswordToken(data.restoreToken) in verifyCodeMutation success callback.

How can I wait for it?

Any way I can handle it via React-Query tools?

  const { mutateAsync: verifyCodeMutation } = useMutation(verifyCode, {
    onSuccess: ({ data }) => setRestorePasswordToken(data.restoreToken),
  });

  const { mutateAsync: newPasswordMutation } = useMutation(createNewPassword, {
    enabled: restorePasswordToken,
    onSuccess: () => setPasswordResetSuccessfull(true),
  });

  const onRestorePasswordSubmit = ({ email }) => {
    restorePasswordMutation(email);
  };

  const onVerificationCodeSubmit = async ({ verificationCode, password }) => {
    await verifyCodeMutation({ verificationCode, restoreToken });
    newPasswordMutation({ password, restorePasswordToken });
  };
0

2 Answers 2

44

Dependent mutations can basically be solved in 3 different ways:

1) make multiple calls inside the mutateFn:

const mutate = useMutation((data) =>
  axios.post('/something', { data })
    .then((somethingResult) =>
        axios.put('/somethingElse', { somethingResult })
  )
)
<button onClick={() => mutate('data') />

advantage would be one mutation with one loading state. disadvantage would be you can't easily trigger them separately if you'd need to.

2) with mutateAsync:

const mutate1 = useMutation((data) => axios.post('/something', { data }))
const mutate2 = useMutation(somethingResult) => axios.put('/somethingElse', { somethingResult })

<button onClick={async () => {
  try {
    const somethingResult = await mutate1.muteateAsync('data')
    const result = await mutate2.mutateAsync(somethingResult)
  } catch {}
}} />

a bit boilerplate-y and you'd need to combine loading states very likely

3) with mutate and callbacks:

const mutate1 = useMutation((data) => axios.post('/something', { data }))
const mutate2 = useMutation(somethingResult) => axios.put('/somethingElse', { somethingResult })

<button onClick={() => {
    mutate1.mutate('data', {
      onSuccess: mutate2.mutate
    })
}} />

separated, but still quite concise. will get messy with more than 2 mutations, and the end-result would only be available in the onSuccess callback of the second mutation if you need it

Sign up to request clarification or add additional context in comments.

Comments

10

In case it will help someone: I've just executed second mutation in first one onSuccess

  const { mutateAsync: verifyCodeMutation } = useMutation(verifyCode, {
    onSuccess: ({ data }) => {
      setRestorePasswordToken(data.restoreToken);
      const password = getValues("password");
      newPasswordMutation({ password, restorePasswordToken });
    },
  });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.