redux-thunk

@reduxjs/toolkit

Redux Toolkit includes these APIs:

  • configureStore(): wraps createStore to provide simplified configuration options and good defaults. It can automatically combine your slice reducers, adds whatever Redux middleware you supply, includes redux-thunk by default, and enables use of the Redux DevTools Extension.

ๅฆ‚ๆžœ็”จ@reduxjs/toolkitไพ†ๅฏซredux๏ผŒๅฏ็›ดๆŽฅไฝฟ็”จไปฅไปฅไธ‹redux-thunk็š„ๅŠŸ่ƒฝ(ๅพ€ไธ‹็œ‹)

redux


  • While the thunk middleware is not directly included with the Redux core library, it is used by default in our @reduxjs/toolkit package.

็•ถไฝ ๆฒ’ๆœ‰็”จ@reduxjs/toolkit๏ผŒๅ–ฎ็ด”ไฝฟ็”จ redux
้œ€่ฆ่‡ช่กŒ npm i redux-thunk
ๅŠ ้€ฒ configureStore ็š„ middleware ่ฃก

ๅฏไปฅ่ฎŠๆˆ่ฎ“ไฝ ๅ†่‡ช่กŒ่จญๅฎšไธญ็š„action่ฃก๏ผŒๅฏdispatchๅคš้‡action๏ผŒ่ฎŠๅพ—ๅœจaction่ฃกๅฏไปฅ็…ง่ฆๅ‰‡ไฝฟ็”จ dispatch ๅŠ getState ็•ถๅƒๆ•ธ็”จ

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.

stackoverflow( basic ):

โ€‹โ€‹โ€‹โ€‹import { createStore, applyMiddleware } from 'redux'
โ€‹โ€‹โ€‹โ€‹import thunk from 'redux-thunk'

โ€‹โ€‹โ€‹โ€‹const store = createStore(
โ€‹โ€‹โ€‹โ€‹  reducer,
โ€‹โ€‹โ€‹โ€‹  applyMiddleware(thunk)
โ€‹โ€‹โ€‹โ€‹)

โ€‹โ€‹โ€‹โ€‹// It still recognizes plain object actions
โ€‹โ€‹โ€‹โ€‹store.dispatch({ type: 'INCREMENT' })

โ€‹โ€‹โ€‹โ€‹// But with thunk middleware, it also recognizes functions
โ€‹โ€‹โ€‹โ€‹store.dispatch(function (dispatch) {
โ€‹โ€‹โ€‹โ€‹  // ... which themselves may dispatch many times
โ€‹โ€‹โ€‹โ€‹  dispatch({ type: 'INCREMENT' })
โ€‹โ€‹โ€‹โ€‹  dispatch({ type: 'INCREMENT' })
โ€‹โ€‹โ€‹โ€‹  dispatch({ type: 'INCREMENT' })

โ€‹โ€‹โ€‹โ€‹  setTimeout(() => {
โ€‹โ€‹โ€‹โ€‹    // ... even asynchronously!
โ€‹โ€‹โ€‹โ€‹    dispatch({ type: 'DECREMENT' })
โ€‹โ€‹โ€‹โ€‹  }, 1000)
โ€‹โ€‹โ€‹โ€‹})

example (react-redux):

store.js

โ€‹โ€‹โ€‹โ€‹import { createStore, applyMiddleware } from "redux";
โ€‹โ€‹โ€‹โ€‹import { composeWithDevTools } from "redux-devtools-extension";
โ€‹โ€‹โ€‹โ€‹import thunk from "redux-thunk";
โ€‹โ€‹โ€‹โ€‹import rootReducer from "./reducers";

โ€‹โ€‹โ€‹โ€‹const initialState = {};

โ€‹โ€‹โ€‹โ€‹const middleware = [thunk];

โ€‹โ€‹โ€‹โ€‹const store = createStore(
โ€‹โ€‹โ€‹โ€‹  rootReducer,
โ€‹โ€‹โ€‹โ€‹  initialState,
โ€‹โ€‹โ€‹โ€‹  composeWithDevTools(applyMiddleware(...middleware))
โ€‹โ€‹โ€‹โ€‹);

โ€‹โ€‹โ€‹โ€‹export default store;

component

โ€‹โ€‹โ€‹โ€‹import React, { useEffect } from 'react';
โ€‹โ€‹โ€‹โ€‹import { useDispatch } from 'react-redux';
โ€‹โ€‹โ€‹โ€‹import { getOrderDetails } from '../actions/orderActions';


โ€‹โ€‹โ€‹โ€‹const OrderScreen = ({ match }) => {
โ€‹โ€‹โ€‹โ€‹  const orderId = match.params.id;
โ€‹โ€‹โ€‹โ€‹  const dispatch = useDispatch();

โ€‹โ€‹โ€‹โ€‹  useEffect(() => {
โ€‹โ€‹โ€‹โ€‹    dispatch(getOrderDetails(orderId));
โ€‹โ€‹โ€‹โ€‹  }, [dispatch, orderId]);
โ€‹โ€‹โ€‹โ€‹  
โ€‹โ€‹โ€‹โ€‹  return ( ... )
โ€‹โ€‹โ€‹โ€‹ }

action

โ€‹โ€‹โ€‹โ€‹import axios from 'axios';
โ€‹โ€‹โ€‹โ€‹import {
โ€‹โ€‹โ€‹โ€‹  ORDER_DETAILS_REQUEST,
โ€‹โ€‹โ€‹โ€‹  ORDER_DETAILS_SUCCESS,
โ€‹โ€‹โ€‹โ€‹  ORDER_DETAILS_FAIL,
โ€‹โ€‹โ€‹โ€‹} from '../constants/orderConstants';
โ€‹โ€‹โ€‹โ€‹

โ€‹โ€‹โ€‹โ€‹export const getOrderDetails = (orderId) => async (dispatch, getState) => {
โ€‹โ€‹โ€‹โ€‹  try {
โ€‹โ€‹โ€‹โ€‹    dispatch({ type: ORDER_DETAILS_REQUEST });

โ€‹โ€‹โ€‹โ€‹    const {
โ€‹โ€‹โ€‹โ€‹      userLogin: { userInfo },
โ€‹โ€‹โ€‹โ€‹    } = getState();

โ€‹โ€‹โ€‹โ€‹    const config = {
โ€‹โ€‹โ€‹โ€‹      headers: {
โ€‹โ€‹โ€‹โ€‹        Authorization: `Bearer ${userInfo.token}`,
โ€‹โ€‹โ€‹โ€‹      },
โ€‹โ€‹โ€‹โ€‹    };
โ€‹โ€‹โ€‹โ€‹    const { data } = await axios.get(`/api/orders/${orderId}`, config);

โ€‹โ€‹โ€‹โ€‹    dispatch({ type: ORDER_DETAILS_SUCCESS, payload: data });
โ€‹โ€‹โ€‹โ€‹  } catch (err) {
โ€‹โ€‹โ€‹โ€‹    dispatch({
โ€‹โ€‹โ€‹โ€‹      type: ORDER_DETAILS_FAIL,
โ€‹โ€‹โ€‹โ€‹      payload:
โ€‹โ€‹โ€‹โ€‹        err.response && err.response.data.message
โ€‹โ€‹โ€‹โ€‹          ? err.response.data.message
โ€‹โ€‹โ€‹โ€‹          : err.message,
โ€‹โ€‹โ€‹โ€‹    });
โ€‹โ€‹โ€‹โ€‹  }
โ€‹โ€‹โ€‹โ€‹};
  • With a plain basic Redux store, you can only do simple synchronous updates by dispatching an action. Middleware extends the store's abilities, and lets you write async logic that interacts with the store.

    Thunks are the recommended middleware for basic Redux side effects logic, including complex synchronous logic that needs access to the store, and simple async logic like AJAX requests.

  • redux-thunk is the most commonly used middleware for working with both synchronous and async logic outside of components

  • With Redux Thunk action creators can dispatch the result of other action creators and not even think whether those are synchronous or asynchronous: