Redux and its source code

It has been a year since I transferred from VUE to React unconsciously, and my understanding of React has also changed from application to principle. In the spirit of learning, I write this series, hoping that the great god can give me more advice, and also hope to bring some help to the students.

1. Initialize the project

NPX create-react-app myName = NPX create-react-app myName = NPX create-react-app myName = NPX create-react-app myName = NPX create-react-app

2. Initialize the page directory configuration

Here I have removed some unnecessary default files, you can optimize according to your needs:

1: Create the pages and Store folders in the SRC directory, create the index. JSX file in the pages directory, and create the store.js file in the Store folder

2: Run NPM install –save redux to install redux

Let’s use redux first:

Index. JSX complete code

import React, { Component } from 'react'

import store from '@/store/store'

export default class index extends Component {
    componentDidMount() { 
        // Subscribe to the react forceUpdate method by default and rerender it
        store.subscribe(() = > { 
            this.forceUpdate()
        })
    }
    add = () = > {
        store.dispatch({type:"ADD"})
    }
    minus = () = > { 
        store.dispatch({type:"MINUS"})}render() {
        return (
            <div className="le_home">Redux source code learning<p>{store.getState()} </p>
                <button onClick={ this.add} >increase</button>
                <button onClick={ this.minus} >To reduce</button>
            </div>)}}Copy the code

Complete code under store:

import { createStore } from 'redux'
function countReducer(state = 0, action) { 
    switch (action.type) {
        case 'ADD':
            return state+1
        case 'MINUS':
            return state-1
        default:
            return state
    }
}

let store = createStore(countReducer)

export default store
Copy the code

After the project runs, we can click the button to see the change of the number, isn’t it very exciting? Let’s discover the mystery of Redux.

3. Create myStore.js under store, which is our own redux

First, analyze the structure of createStore function

1: Received a parameter (Reducer)

2: There are three built-in methods: Subscribe, dispatch, and getState.

Two: here I directly give the code, with detailed comments

export function createStore(reduce,enhancer) { 
    if (enhancer) { 
        return enhancer(createStore(reduce))
    }
    // Define the initial value
    let currentData = undefined
    // Save the listener function
    let currentLinser = []
    / / get the value
    function getState() { 
        return currentData
    }
    / / value
    function dispatch(action) { 
        currentData = reduce(currentData, action)
        currentLinser.forEach(a= >a())
    }
    The forceUpdate() method of React is called to rerender render
    function subscribe(cb) { 
        currentLinser.push(cb)
    }
    // The initial value is returned when we subscribe
    dispatch({type:'dsfs'})
    return {
        getState,
        dispatch,
        subscribe
    }
}
Copy the code

Now that we’ve done the basic functionality of Redux, it’s pretty simple

Redux middleware

Redux does not have the ability to write logic for actions, so we need applyMiddleware, the second important function of Redux

Let’s start by installing the following react-Thunk middleware and using it to see what happens! The console executes NPM install –save react-thunk

1: increment under store.js code

import { createStore,applyMiddleware } from 'redux'
import thunk from "redux-thunk";
let store = createStore(countReducer,applyMiddleware(thunk))
Copy the code

2: added under index, JSX code

// Modify the add function to add some logic
add = () = > { 
    store.dispatch(dispatch= > { 
        // Here you can volatilize freely
        setTimeout(() = > { 
            dispatch({type:"ADD"})},1000)})}Copy the code

Implementation of the applyMiddleware function

Create the applyMiddleware function under myStore.js

export function applyMiddleware(. middlewares) {
    // Return an enhanced function directly
    return createStore= > (. args) = > {
        conststore = createStore(... args)let dispatch = store.dispatch
        const midApi = {
            getState:store.getState,
            dispatch:(. args) = >dispatch(... args) }// Get the status value and issue the action
        const middlewareChain = middlewares.map(middleware= > middleware(midApi))
        // Aggregate into a function. Here is a classic responsibility chain design patterndispatch = compose(... middlewareChain) (store.dispatch)return {
            ...store,
            dispatch
        }
    }
}
// Aggregate function
export function compose(. funcs) {
    if (funcs.length === 0) {
        return arg= > arg
    }
    if (funcs.length === 1) {
        return funcs[0}} The data reduce method is used to calculate the value from left to right, and the aggregation function is usedreturn funcs.reduce((a, b) = > (. args) = >a(b(... args))) }Copy the code

The react-Redux react-redux react-redux react-redux react-redux react-redux react-redux