Who’d a Thunk?
Asynchronous code in React-Redux.
You should understand the basics of Redux before trying to implement a thunk. This is slightly more advanced in the Redux world.
What the heck is a ‘thunk’? There is also an article from their docs here. It just happens to be titled the same way I start this paragraph. Funny that. A simplified explanation is that it’s a wrapper function as a sort of middleware that returns another function. This allows you to execute code before you return the next function (a function that the thunk returns).
Why is this a thing? Redux only allows synchronous actions to be executed in its reducers or actions creators, so you can’t make API calls or use a setTimeout or anything.
When should you use this? Whenever you perform asynchronous actions in Redux. This is more so I have a nice ‘www’ on the side so my post is more internet-ey.
How do we do this then? First, I’ll be explaining this with Redux hooks because I am a sane engineer who values his time.
Here is how we tell Redux we are using middleware:
// index.jsimport { createStore, compose, applyMiddleware } from "redux";
import searchReducer from "./redux/reducers/searchReducer";
import thunk from "redux-thunk";const store = createStore( searchReducer, applyMiddleware(thunk) );
Let’s say we’ve made a form that queries an API that searches the site for matches of the user’s input. Everything up until we dispatch our action is the same as usual. I like to use action creators but you can do it without them if you’d like. With that, here is what my code looks like:
// redux/actions/search.jsimport * as actions from "../redux/actions/search";
export const saveSearch = (searchText, data) => { return { type: actionTypes.ADD_SEARCH, text: searchText, searchResults: data, };};export const addSearch = (searchText) => { return (dispatch) => { fetch(`http://API.com/notArealAPI/search?query=${searchText}`) .then((response) => response.json()) .then((data) => dispatch(saveSearch(searchText, data)));};
Now, this is where we can talk about the weird part where we make an action for our action. The saveSearch function above is returning our ADD_SEARCH action creator… and that’s exactly what we want because if we called addSearch in our second ‘then’ block, well then we would have an infinite loop. I love loops but not infinite loops. They are too loopy. I’ll stop while I am ahead.
Really this is all there is to it. I do nothing different in my reducer. There are other ways to manage this but I like this solution since it’s straightforward and logical. Hopefully, this helps my Redux using friends be as asynchronous as they want in a predominantly synchronous world.
Happy hacking!