In the last article, we integrated synchronous Redux into our project. In this article, we will use asynchronous Actions to optimize our code in Redux
State
Let’s remember our store type first
type Person = {
id: number;
name: string;
};
type AppState = {
people: Person[];
};
Copy the code
so? Our store contains a people field, which is an array type containing id/name
We just need to define some cleaner store states so we can focus on the Redux Store and how the React component interacts with it in a strongly typed way.
Use asynchronous actions to modify the state in the store
We use Redux Thunk middleware to implement Redux’s asynchronous action.
Where do you add this thing? Add applyMiddleware when creating a store, i.e., createStore. ApplyMiddleware is an API from Redux that allows you to add middleware to the Store
import { combineReducers, createStore, applyMiddleware } from 'redux';
import type { Store } from 'redux';
import thunk from 'redux-thunk';
import type { AppState } from './data.d';
import peopleReducer from './reducers/index';
const rootReducer = combineReducers<AppState>({
people: peopleReducer,
});
function configureStore() :Store<AppState> {
const store = createStore(rootReducer, undefined, applyMiddleware(thunk));
return store;
}
const storeData = configureStore();
export default storeData;
Copy the code
Actions and actions create functions
Now, let’s change the action creation function to be asynchronous. Here is the asynchronous action with the user name added
// src/redux/actions/index.ts
import type { Dispatch } from "redux";
function wait(ms: number) :Promise<void> {
return new Promise((resolve) = > setTimeout(resolve, ms));
}
const addPerson = (personName: string) = > async (
dispatch: Dispatch<AddPersonAction>
) => {
await wait(200);
dispatch({
type: "AddPerson".payload: personName,
} as const);
};
Copy the code
In our example, we are forgery an asynchronous operation (such as an interface request) with the WAIT delay function.
addPerson
Function returns a function, rather than an Action object like the original synchronous function.- The inner function takes one argument
dispatch
Function that dispatches an action
Note that we explicitly set the type of the Dispatch parameter using Dispatch
. Dispatch is a generic type provided by Redux, and we pass the type AddPersonAction to Dispatch.
Here is the definition of the AddPersonAction type
type AddPersonAction = {
readonly type: "AddPerson";
readonly payload: string;
};
Copy the code
Next, we modify the action creation function to delete the user
// src/redux/actions/index.ts
type RemovePersonAction = {
readonly type: "RemovePerson";
readonly payload: number;
};
const removePerson = (id: number) = > async (
dispatch: Dispatch<RemovePersonAction>
) => {
await wait(200);
dispatch({
type: "RemovePerson".payload: id,
} as const);
};
Copy the code
Reducer
The action parameter types in Reducer are different from those in the synchronous version
type Actions = AddPersonAction | RemovePersonAction;
Copy the code
In the synchronized version of the code, we implemented the action type with TS’s automatic type, but here we need to create the action type.
The reducer functions are the same as those of the synchronized version
function peopleReducer(state: Person[] = [], action: Actions) {
switch (action.type) {
case "AddPerson":
return state.concat({
id: state.length + 1.name: action.payload,
});
case "RemovePerson":
return state.filter((person) = >person.id ! == action.payload);default:
neverReached(action);
}
return state;
}
function neverReached(never: never) {}
Copy the code
Link component
Connect the React component to the Store. UseSelector is used to get data from the store
const people: Person[] = useSelector((state: AppState) = > state.people);
Copy the code
UseDispatch dispatches the action
constdispatch = useDispatch(); .const handleSubmit = (e: React.FormEvent<HTMLFormElement>) = >{ e.preventDefault(); dispatch(addPerson(newPerson)); . }; .const dispatchNewPerson = (id: number) = > () = >{ dispatch(removePerson(id)); }; . <button onClick={dispatchNewPerson(person.id)}>Remove</button>Copy the code
conclusion
Redux needs libraries like Redux Thunk to handle asynchronous operations.
Async action creation returns a function that dispatches an action(note: the action creation function in a synchronous Redux returns an object)
However, there is a popular library called Redux Saga that handles asynchronous Redux operations, which we will cover briefly later
Reference documentation
www.carlrippon.com/managing-ap…