I was migrating from Apollo client to Redux toolkit and I am confusing how to use the result(success or error) of API call with createAsyncThunk
and call history.push('/')
and setSubmitting(false)
in my React component.
Example how I did with Formik
and Apollo Client
:
onSubmit={async (values, { setSubmitting }) => {
signInMutation({
variables: {
email: values.email,
password: values.password,
},
}).then(
(response) => {
if (response.data.signIn.accessToken) {
localStorage.setItem(
AUTH_TOKEN,
response.data.signIn.accessToken,
);
if (response.data.signIn.User.isNew) {
history.push('/welcome-page');
} else {
history.push('/');
}
setSubmitting(false);
}
},
(err) => {
console.log(`error signin ${err}`);
enqueueSnackbar(err.message, {
variant: 'error',
});
setSubmitting(false);
},
);
When you call createAsyncThunk
, it will return an Action Creator
which redux-thunk
can use.
You should use the function like this:
const actionCreator = createAsyncThunk('prefix', async function echo(text) {
return text;
});
// app.js
import { unwrapResult } from '@reduxjs/toolkit';
function App() {
const dispatch = useDispatch();
return (
<button
onClick={() => {
dispatch(actionCreator('233'))
.then(unwrapResult)
.then((result) => {
console.log(result); // => 233
})
.catch((error) => {
console.error(error); // if there is an error
});
}}
>
Echo
</button>
);
}
This is what unwrapResult
does:
// @reduxjs/toolkit
export function unwrapResult<R extends ActionTypesWithOptionalErrorAction>(
returned: R
): PayloadForActionTypesExcludingErrorActions<R> {
if ('error' in returned) {
throw returned.error
}
return (returned as any).payload
}
To handle errors, there are two ways. The first is to throw them directly, and the second is to return rejectWithValue
.
async function echo(text, { rejectWithValue }) {
if (Math.random() < 0.5) {
// throw new Error('error msg');
// return rejectWithValue('error value');
}
return text;
}
dispatch(actionCreator('233'))
.then(unwrapResult)
.then((result) => {
console.log(result); // => 233
})
.catch((error) => {
// by throw new Error('error msg');
console.log(error.message); // => error msg
// by return rejectWithValue('error value')
console.log(error); // => error value
});