Async Error Handling Logic in Thunks
Handling errors in a Redux toolkit application using thunks.
We'll cover the following
Introduction
As you’ll come to see, handling errors in thunks is just as straightforward as the loading state handled in the last lesson.
Let’s get right into it. But first, here’s the flow we’re gunning for within the fetchTweets
thunk:
- Wrap API call in a try-catch block.
- Catch errors if they occur and dispatch a new action.
- Save error message.
- Handle error state in the application UI.
// before
export const fetchTweets = (searchValue, numberOfResults) => async (
dispatch
) => {
dispatch(isLoadingTweets());
const tweets = await findTweets(searchValue, numberOfResults);
dispatch(loadingTweetsSuccess(tweets));
};
// now
export const fetchTweets = (searchValue, numberOfResults) => async (
dispatch
) => {
// wrap in a try catch
try {
dispatch(isLoadingTweets());
const tweets = await findTweets(searchValue, numberOfResults);
dispatch(loadingTweetsSuccess(tweets));
} catch (error) {
// to be described
}
};
We’re going to dispatch a loadingTweetsFailed
action if there’s an error. Let’s go ahead and create an associating reducer in the slice object.
const finderSlice = createSlice({
name: "finder",
initialState,
reducers: {
// ...
// see this 👇
loadingTweetsFailed(state, payload) {
state.isLoading = false;
state.error = payload;
},
},
});
// add loadingTweetsFailed to the exported action creators
export const {
isLoadingTweets,
loadingTweetsSuccess,
loadingTweetsFailed, // 👈 see this
} = finderSlice.actions;
This is awesome. loadingTweetsFailed
may now be invoked with a payload. We’ll have this payload be whatever the error message is:
export const fetchTweets = (searchValue, numberOfResults) => async (
dispatch
) => {
try {
dispatch(isLoadingTweets());
const tweets = await findTweets(searchValue, numberOfResults);
dispatch(loadingTweetsSuccess(tweets));
} catch (error) {
// see this 👇
// grab error message and dispatch action
const errorMsg = error.toString();
dispatch(loadingTweetsFailed(errorMsg));
}
};
With this action dispatched now, we can handle the error state within the UI. This all happens in Finder.js
.
First, let’s grab the error state:
// Finder.js
export function Finder() {
// ...
// deconstruct 'error'
const { tweets, isLoading, error } = useSelector((state) => state.finder);
}
Then, render some UI based on that:
import {
// ...,
Alert,
AlertIcon,
AlertDescription,
AlertTitle,
CloseButton,
} from "@chakra-ui/react";
export function Finder() {
// ...
if (error) {
return (
<Alert status="error">
<AlertIcon />
<AlertTitle mr={2}>An Error occurred!</AlertTitle>
<AlertDescription>
We couldn't fetch tweets right now. Please try again later.
</AlertDescription>
<CloseButton position="absolute" right="8px" top="8px" />
</Alert>
);
}
}
And now we should have the following UI whenever an error is triggered from fetching the tweets:
Get hands-on with 1200+ tech skills courses.