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: