### Install Redux Thunk Package Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md Instructions for installing the `redux-thunk` package using npm or yarn for manual Redux setups. ```sh npm install redux-thunk yarn add redux-thunk ``` -------------------------------- ### Apply Redux Thunk Middleware Manually Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md Illustrates how to integrate Redux Thunk into a Redux store using `applyMiddleware` with `createStore` for manual setup. ```js import { createStore, applyMiddleware } from 'redux' import { thunk } from 'redux-thunk' import rootReducer from './reducers/index' const store = createStore(rootReducer, applyMiddleware(thunk)) ``` -------------------------------- ### Redux Store Setup and Basic Action Creators Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md This snippet demonstrates how to set up a Redux store with the `redux-thunk` middleware and defines several basic action creators that return plain action objects. These actions represent simple facts or events that can be dispatched directly. ```JavaScript import { createStore, applyMiddleware } from 'redux' import { thunk } from 'redux-thunk' import rootReducer from './reducers' // Note: this API requires redux@>=3.1.0 const store = createStore(rootReducer, applyMiddleware(thunk)) function fetchSecretSauce() { return fetch('https://www.google.com/search?q=secret+sauce') } // These are the normal action creators you have seen so far. // The actions they return can be dispatched without any middleware. // However, they only express “facts” and not the “async flow”. function makeASandwich(forPerson, secretSauce) { return { type: 'MAKE_SANDWICH', forPerson, secretSauce, } } function apologize(fromPerson, toPerson, error) { return { type: 'APOLOGIZE', fromPerson, toPerson, error, } } function withdrawMoney(amount) { return { type: 'WITHDRAW', amount, } } // Even without middleware, you can dispatch an action: store.dispatch(withdrawMoney(100)) ``` -------------------------------- ### Configure Redux Store with Redux Toolkit Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md Demonstrates how Redux Toolkit's `configureStore` automatically includes the thunk middleware, simplifying store setup without explicit middleware application. ```js import { configureStore } from '@reduxjs/toolkit' import todosReducer from './features/todos/todosSlice' import filtersReducer from './features/filters/filtersSlice' const store = configureStore({ reducer: { todos: todosReducer, filters: filtersReducer, }, }) // The thunk middleware was automatically added ``` -------------------------------- ### Inject Custom Argument with Manual Redux Setup Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md Explains how to inject a custom argument into the thunk middleware using `withExtraArgument()` when setting up the Redux store manually with `applyMiddleware`. ```js const store = createStore(reducer, applyMiddleware(withExtraArgument(api))) ``` -------------------------------- ### Chaining Thunk Dispatches with Promises Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md This example demonstrates how the return value of a thunk (e.g., a Promise from an API call) is made available as the return value of `store.dispatch`. This allows for chaining `.then()` calls on the dispatch result, enabling sequential asynchronous operations and better control flow. ```JavaScript // It even takes care to return the thunk’s return value // from the dispatch, so I can chain Promises as long as I return them. store.dispatch(makeASandwichWithSecretSauce('My partner')).then(() => { console.log('Done!') }) ``` -------------------------------- ### Using Redux Thunks in React Components for Data Fetching Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md This example demonstrates how to integrate Redux thunks with React components. Thunks can be dispatched from lifecycle methods like `componentDidMount` and `componentDidUpdate` to fetch data or perform other asynchronous operations when the component mounts or its props change, ensuring data is loaded as needed. ```JavaScript // I can also dispatch a thunk async action from a component // any time its props change to load the missing data. import { connect } from 'react-redux' import { Component } from 'react' class SandwichShop extends Component { componentDidMount() { this.props.dispatch(makeASandwichWithSecretSauce(this.props.forPerson)) } componentDidUpdate(prevProps) { if (prevProps.forPerson !== this.props.forPerson) { this.props.dispatch(makeASandwichWithSecretSauce(this.props.forPerson)) } } render() { return
{this.props.sandwiches.join('mustard')}
} } export default connect(state => ({ sandwiches: state.sandwiches, }))(SandwichShop) ``` -------------------------------- ### Redux Thunk Conditional Dispatch Action Creator Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md This JavaScript example illustrates a Redux Thunk action creator that performs conditional dispatch. The `incrementIfOdd` function uses `getState` to access the current `counter` value and dispatches `increment` only if the counter is odd, preventing dispatch if the condition is not met. ```javascript function incrementIfOdd() { return (dispatch, getState) => { const { counter } = getState() if (counter % 2 === 0) { return } dispatch(increment()) } } ``` -------------------------------- ### Import Redux Thunk (CommonJS) Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md Shows how to import the `thunk` named export when using CommonJS. ```js const { thunk } = require('redux-thunk') ``` -------------------------------- ### Import Redux Thunk (ES Modules) Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md Shows how to import the `thunk` named export when using ES modules. ```js import { thunk } from 'redux-thunk' ``` -------------------------------- ### Redux Thunk Async Action Creator Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md This JavaScript code demonstrates how to create an asynchronous action creator using Redux Thunk. The `incrementAsync` function returns a thunk that dispatches the `increment` action after a 1-second delay, showcasing how to perform async operations with access to `dispatch`. ```javascript const INCREMENT_COUNTER = 'INCREMENT_COUNTER' function increment() { return { type: INCREMENT_COUNTER, } } function incrementAsync() { return dispatch => { setTimeout(() => { // Yay! Can invoke sync or async actions with `dispatch` dispatch(increment()) }, 1000) } } ``` -------------------------------- ### Creating and Dispatching a Thunk Action Creator for Async Operations Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md This snippet introduces a 'thunk' action creator, `makeASandwichWithSecretSauce`, which returns a function instead of a plain object. This function is intercepted by `redux-thunk` and receives `dispatch` and `getState` as arguments, allowing it to perform asynchronous operations (like fetching data) and then dispatch other actions based on the result. ```JavaScript // Meet thunks. // A thunk in this context is a function that can be dispatched to perform async // activity and can dispatch actions and read state. // This is an action creator that returns a thunk: function makeASandwichWithSecretSauce(forPerson) { // We can invert control here by returning a function - the "thunk". // When this function is passed to `dispatch`, the thunk middleware will intercept it, // and call it with `dispatch` and `getState` as arguments. // This gives the thunk function the ability to run some logic, and still interact with the store. return function (dispatch) { return fetchSecretSauce().then( sauce => dispatch(makeASandwich(forPerson, sauce)), error => dispatch(apologize('The Sandwich Shop', forPerson, error)), ) } } // Thunk middleware lets me dispatch thunk async actions // as if they were actions! store.dispatch(makeASandwichWithSecretSauce('Me')) ``` -------------------------------- ### Composing Complex Asynchronous Flows with Nested Thunks Source: https://github.com/reduxjs/redux-thunk/blob/master/README.md This snippet illustrates how to build sophisticated asynchronous control flows by dispatching both plain actions and other thunks from within a thunk. It shows how `Promise.all` can be used to manage parallel asynchronous operations and how `getState()` can be used to make conditional decisions within the thunk. ```JavaScript // In fact I can write action creators that dispatch // actions and async actions from other action creators, // and I can build my control flow with Promises. function makeSandwichesForEverybody() { return function (dispatch, getState) { if (!getState().sandwiches.isShopOpen) { // You don’t have to return Promises, but it’s a handy convention // so the caller can always call .then() on async dispatch result. return Promise.resolve() } // We can dispatch both plain object actions and other thunks, // which lets us compose the asynchronous actions in a single flow. return dispatch(makeASandwichWithSecretSauce('My Grandma')) .then(() => Promise.all([ dispatch(makeASandwichWithSecretSauce('Me')), dispatch(makeASandwichWithSecretSauce('My wife')), ]), ) .then(() => dispatch(makeASandwichWithSecretSauce('Our kids'))) .then(() => dispatch( getState().myMoney > 42 ? withdrawMoney(42) : apologize('Me', 'The Sandwich Shop'), ), ) } } // This is very useful for server side rendering, because I can wait // until data is available, then synchronously render the app. store .dispatch(makeSandwichesForEverybody()) .then(() => response.send(ReactDOMServer.renderToString(