How to Use Thunks with Redux Toolkit and TypeScript
Last time we used Redux Toolkit to create a todo app. Since RTK is considered to be the standard way to write redux applications, we will use thunks with Redux Toolkit to write asynchronous logic as well. Thunks are a way to manage side effects when working with Redux. For instance, when we want to fetch some data from a server we need to perform an HTTP request. That request is a side effect because it interacts with the “outer world”. Redux itself doesn't know anything about side effects in an app. All the work is done in the redux-thunk middleware. It extends the store's abilities and lets you write async logic that interacts with the store. Redux Toolkit's configureStore function automatically sets up the thunk middleware by default. Right now we have a todo app that works synchronously, so we can only use the runtime storage to store the user data. In real-life applications, we would need to store user's data in some kind of persistent storage, on a server for example. Let's change our app a bit and, as an example, create a method to load todos from the server and show them. First of all, we're going to slightly refactor our previous code. We will extract our useTypedSelector from features/todos/TodoList.tsx to app/store.ts : ...This will help us to re-use this function in another component later. Also, we will extract some todos types into features/todos/types.ts : ...Which will help us to cover the API requests with types. As a backend, we will use JSON-placeholder . It allows us to fetch a list of todo-objects that we can render in our UI. The endpoint we use returns a list of todo-objects RTK provides a function called createAsyncThunk for creating thunks. Let's start with creating one: Let's write the real request logic using our placeholder backend: Cool, now it's working. However, the result we return is not typed. TypeScript yet doesn't know about the structure of data we return. For typing the result , we're going to need Todo type we extracted earlier: Okay, now our fetchTodos function doesn't take any argument. But let's think about a situation when we need to control the amount of fetched todos. We could use a function argument for that: The only thing left to cover is errors. Imagine that the server responded with a status 400. In this case, we would need to tell our users that todos aren't loaded and show the error message. Now, let's add our thunk to todosSlice . For that, we need to slightly change our TodosState : After it's done, let's define a selector for getting the status value: Finally, let's add reducers for handling our fetchTodos actions: The last thing to do is to use the fetchTodos thunk inside a component. Let's create a button, click on which will fetch a list of todos from a server. Now we can use this component to load todos from the server.