Michael Hueter
Instructor at Rithm School and Full-Stack Software Developer
In computer programming, a thunk is a subroutine used to inject an additional calculation into another subroutine. Thunks are primarily used to delay a calculation until its result is needed, or to insert operations at the beginning or end of the other subroutine. They have a variety of other applications in compiler code generation and modular programming.
The term originated as a jocular derivative of "think".
Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.
redux-thunk is a plug-in to extend redux (via middleware).
TL;DR it lets you do async stuff
1. npm i redux-thunk
2. Wherever you are calling createStore:
import { createStore, compose, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
/**
* Build a Redux Store and apply middleware
*/
function configureStore() {
const store = createStore(
rootReducer,
// enable the dev tools extension if you have it installed
compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : f => f
)
);
return store;
}
export default configureStore;
An action creator...that returns a function...that can dispatch other actions.
function incrementIfOdd() {
// the function has two params:
// dispatch calls the reducer with an action
// getState fetches the current Redux state from the store
return (dispatch, getState) => {
const { counter } = getState();
if (counter % 2 === 0) {
return;
}
dispatch(increment());
};
}
export function fetchTodosRequest() {
// THUNK!
return async (dispatch, getState) => {
// dispatch an action describing that we are making a request
dispatch({ type: FETCH_TODOS_REQUEST });
try {
// call the API (async operation)
const todos = await fetchTodos();
// dispatch a success action if it works
dispatch(fetchTodosSuccess(todos));
} catch (err) {
// dispatch a fail action if API call fails
dispatch(fetchTodosFail(err));
// manually reject the promise
return Promise.reject();
}
};
}
async componentDidMount() {
// before component renders, fetch todos first
try {
await this.props.fetchTodos();
} catch(e) {
return;
}
// if we get here successfully, we're done loading!
this.setState({
loading: false
});
}
The following code works as long as your thunk returns a Promise (async functions do this automatically)
By Michael Hueter
How to use thunks to manage asynchronous code in Redux.