'Passing arguments to actions in Redux
I am using the redux toolkit, (the new update of redux in case you're still using the deprecated older version) with React and I am using the createAsyncThunk method (or middleware if you prefer) to perform an API call to my backend API.
Here, I can do two things, either run the async call inside the component and check whether the API call succeeds or fails, and render something based on that, or I can perform the Async API call inside the action creator itself (inside the createSlice in case you're using the Redux toolkit).
Personally, I believe that the second approach is more abstract and cleaner for the components, but the main problem is that I can't handle the errors there. In other words, take this example, I wanted to getAllPosts, I can simply dispatch an action using dispatch(getAllPosts()) within the component, and let the Async logic and error handling be inside the action creator getAllPosts. But in case of a failed Async call, I can't return an error to the component to render a red message saying "there was an error while fetching the posts".
I thought I could pass a callback function as an argument to the getAllPosts action creator, and make this callback function a callback that only runs in case of a failure. ex:
dispatch(getAllPosts(payloadObj, ()=> { /* do something here in case of an error* / } ))
The questions are:
- What do you think about my solution? Is it the best or is there a standardized way of doing this?
- How do I pass the callback function argument I described to the getAllPosts method? Can I simply add a second argument to the
getAllPostsmethod? Or is that not possible in redux-toolkit? Do I have to pass my callback function as the first argument? But having it the first argument will make redux-toolkit wrap it inside apayloadproperty because it's assumed that what I am passing is a new state.
Solution 1:[1]
The correct answer here is to follow the pattern shown in Redux Essentials Part 5: Async Logic - Checking Thunk Results in Components.
If the thunk function returns a promise, that will be returned from dispatch(thatAsyncThunk()).
RTK's createAsyncThunk in particular will end up returning a promise with a special .unwrap() method that either returns the result if successful, or throws an error if it failed.
So, the right technique in a component is:
const fetchPokemonByName = createAsyncThunk(
'fetchPokemonByName',
async (name) => {
const res = await imaginaryPokemonApi.getByName(name);
return res.data;
}
)
// later, in a component
function SomeComponent() {
const dispatch = useDispatch();
const handleClick = async () => {
try {
const pokemon = await dispatch(fetchPokemonByName("pikachu")).unwrap();
console.log("Entry: ", pokemon);
} catch (err) {
console.error("Failed to fetch pokemon: ", err);
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | markerikson |
