After an increasingly busy week, it’s time to start the weekly review. Today I will take a look at redux-Thunk, an open source project with 15.1K star on Github.

As a front-end engineer in the React direction, most people, whether they are interviewed or interviewed, will talk about the implementation of Redux-Thunk, because it is very classic and useful, and the amount of code is touching, just 12 lines of code, It solves the React development problem where the same function supports multiple Dispatches and asynchronous actions (although this is entirely dependent on Redux’s Middleware mechanism).

Next, I will start with:

  • How Redux works
  • Implementation principle of middleware
  • Redux-thunk source code implementation

These three aspects to bring you a thorough grasp of redux-Thunk source code, so as to have a deeper understanding of redux and application. If you are interested in react-Redux-Thunk, you can follow the author’s Master Redux to develop a task management platform

The body of the

Before reading the redux-Thunk source code, we need to grasp the basic working mechanism and middleware implementation principle of Redux, so that we can better understand the source code behind the mystery. To cut a long story short, let’s take a look at some of Redux’s core apis and what they do:reduxThe real problem solved is between the React componentsState sharingandState managementWith the above six core apis we can manage complex state and listen for and trace changes to state. The author summarizes the mechanism as follows:With a basic understanding of how Redux works, let’s look at a practical example:

import actionType from './actionType'

class Actions {
    static start() {
        return {
            type: actionType.CREATE_TODO_DOING
        }
    }

    static ok(data, cb) {
        cb && 'function'= = =typeof cb && cb(data);
        return {
            type: actionType.CREATE_TODO_SUCCESS,
            payload: data
        }
    }

    static fail(data, cb) {
        cb && 'function'= = =typeof cb && cb(data);
        return {
            type: actionType.CREATE_TODO_FAILURE,
            payload: data
        }
    }
}
Copy the code

We know that the action returns a standard object, but we can do some side effects before we return it. We can’t handle asynchronous logic in the action here, and that’s one of the values of Redux-Thunk, which resolves asynchronous calls to actions.

At this point we still can’t go directly into the source analysis of Redux-Thunk, because we still don’t know how to solve the above steps, because we don’t yet understand the middleware mechanism of Redux.

Redux middleware mechanism

When it comes to middleware, those who have used NodeJS may be familiar with it, such as well-known KOA middleware, Express middleware, etc. In fact, the author’s understanding of middleware is a module that does some extra processing in a certain part of the execution flow. The implementation mechanism of middleware is very simple. The framework core execution flow iterates through the incoming middleware and executes in turn. Let’s look at how middleware is used in Redux:

import { createStore, applyMiddleware } from 'redux';
import reducers from './reducers';

const middlewares = applyMiddleware(middleware1, middleware2);
const store = createStore(reducers, middlewares);
Copy the code

Redux-thunk is passed into the applyMiddleware method as a parameter, so it’s easy to guess that the applyMiddleware method has logic to iterate over the parameters.

export default function applyMiddleware(. middlewares) {
	return function enhancer(createStore) {
  	  return function enhancedCreateStore(. args) {
    	conststore = createStore(... args)let dispatch = () = > {
      	  thrownewError('Omit n words here... ')}const middlewareAPI = {
      	  getState: store.getState,
          dispatch: (. args) = >dispatch(... args) }const chain = middlewares.map(function(middleware) {
      	  returnmiddleware(middlewareAPI) }) dispatch = compose(... chain)(store.dispatch)return {
      	  ...store,
          dispatch,
        }
     }
  }
}
Copy the code

From the source code above, in the chain code we find that it stores the result of the call to The applyMiddleware method when the getState parameter is passed in. In the dispatch section, the compose function appears, and those familiar with functional programming can easily guess that it must be a function that implements the batch chain and pumps store.dispatch into it. After analyzing the source code above, we know that each time you run a Dispatch, middleware is used first.

Let’s look at the internal implementation of the compose function:

export default function compose(. funcs) {
  if (funcs.length === 0) {
    return arg= > arg
  }
  
  if (funcs.length === 1) {
    return funcs[0]}return funcs.reduce(function(a, b) {
    return function (. args) {
      returna(b(... args)) } }) }Copy the code

It can be seen from the above code that the final return of compose is a function. If the parameter is greater than one moment, we use Reduce to pass the result returned by the previous function to the next function parameter, so as to realize parameter sharing and passing, which is a classic design.

After mastering the redux middleware implementation principle, we look at the redux-Thunk source code is very easy to understand.

Redux-thunk source analysis

Let’s take a look at what this github star number 15.1k source code is:

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) = > (next) = > (action) = > {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;
Copy the code

Yes, here it isredux-thunkAll source code, is not very nice ~. In the introduction above we learned that the Redux middleware mechanism allows us to get the necessary components in the middlewaredispatch.getState, and two layers of middleware have been invoked before execution. You can then disassemble createThunkMiddleware. The first call to createThunkMiddleware is in the chain phase, which is the source analysis above:So next here is store.dispatch on the second call, and in order to execute multiple dispatches within the same function, we’re going to say if the action is a function, we’re going to execute the Action itself and pass the necessary arguments to it, otherwise we’re going to fire dispatch, Thus we have implemented the support for action functions and asynchronous multiple Dispatches, which is very elegant and simple to read.Learn functions well, go all over the world is not afraid!

Finally, I prepared a practical project based on React+ Redux + Redux-Thunk.

Github.com/MrXujiang/r…

Interested can study reference.

The last

If you want to learn moreH5 game.webpack.node.gulp.css3.javascript.nodeJS.Canvas Data VisualizationAnd other front-end knowledge and actual combat, welcome in the public number “interesting talk front-end” to join our technology group to learn and discuss together, jointly explore the boundary of the front-end.

More recommended

  • Summary of Typescript core knowledge and actual case analysis of the project
  • How do we handle front and back end configuration and request library encapsulation when we encounter cross-domain development (KOA/AXIOS version)
  • Quickly implement SSR (server-side rendering) in your Vue/React app
  • Preliminary study of micro front-end architecture and my front-end technology inventory
  • Implementing a CMS full stack project from 0 to 1 based on nodeJS (Part 1)
  • Implement a CMS full stack project from 0 to 1 based on nodeJS (middle) (source included)
  • CMS full stack project Vue and React (part 2)
  • Develop a component library based on VUE from zero to one
  • Build a front-end team component system from 0 to 1 (Advanced Advanced Prerequisite)
  • Javascript Design Patterns front-end Engineers Need to Know in 15 minutes (with detailed mind maps and source code)