I have a simple app which dispatches an action on first load to populate the store. I want to be able to run a then
method on dispatch
but typescript complains about this.
(According to redux's documentation, the return value of dispatching an action is the return value of the action itself)
Code available in Codesandbox
// app.jsx
function App() {
const dispatch = useAppDispatch();
useEffect(() => {
dispatch(getTodos()).then((todos) => console.log(todos));
// ^^^^^
// Property 'then' does not exist on type '{ type: "GET_TODOS"; payload: Promise<AxiosResponse<Todo[], any>>; }'.
}, []);
return <div className="App">Hello World!</div>;
}
Store Configuration
I use @reduxjs/toolkit
to configure my store and have a redux-promise-middleware
set up for it so that upon "fulfillment" of my promised-based actions an <ACTION>_FULFILLED
action will also be dispatched.
// store.ts
import { configureStore } from '@reduxjs/toolkit';
import promiseMiddleware from 'redux-promise-middleware';
import rootReducer from './reducer';
import { useDispatch } from 'react-redux';
const store = configureStore({
reducer: rootReducer,
middleware: [promiseMiddleware],
});
export type RootState = ReturnType<typeof rootReducer>;
export type AppDispatch = typeof store.dispatch;
export const useAppDispatch = () => useDispatch<AppDispatch>();
export default store;
Reducer
// reducer.ts
import produce, { Draft } from "immer";
import { Action } from "./action";
export type Todo = {
userId: number;
id: number;
title: string;
completed: boolean;
}
interface State {
todos: Todo[];
}
const initialState: State = {
todos: []
};
const reducer = produce((draft: Draft<State>, action: Action) => {
switch (action.type) {
case "GET_TODOS_FULFILLED": {
const todos = action.payload.data;
return todos;
}
}
}, initialState);
export default reducer;
Action
// action.ts
import axios from "axios";
import type { AxiosResponse } from "axios";
import type { Todo } from './reducer'
export const getTodos = (): {
type: "GET_TODOS";
payload: Promise<AxiosResponse<Todo[]>>;
} => ({
type: "GET_TODOS",
payload: axios.get("https://jsonplaceholder.typicode.com/todos")
});
export type Action = ReturnType<typeof getTodos>;