○ Experience of aggregation function

  • Consider: how to execute f1, F2, f3 in sequence?

    // demo_reduce.js
    function f1(arg) {
      console.log('f1', arg);
      return arg;
    }
    
    function f2(arg) {
      console.log('f2', arg);
      return arg;
    }
    
    function f3(arg) {
      console.log('f3', arg);
      return arg;
    }
    Copy the code
  • Method one: function nested writing method

    f3(f2(f1('omg')))
    Copy the code
  • Method two: polymerization writing method

    function compose(. funcs) {
      if (funcs.length === 0) {
        return arg= > arg
      }
    
      if (funcs.length === 1) {
        return funcs[0]}// fn aggregate function fn2 current function
      return funcs.reduce((fn, fn2) = > (. args) = >fn2(fn(... args))) }const res = compose(f1, f2, f3)('omg')
    console.log(res);
    Copy the code

I. Use of Redux

  • Redux workflow

  • The installation

    NPM I REdux or YARN Add redux

  • Use:

    // store.js
    import { createStore } from 'redux'
    
    export const counterReducer = (state = 0, { type, payload = 1 }) = > {
      switch (type) {
        case "ADD":
          return state + payload;
        case "MINUS":
          return state - payload;
        default:
          returnstate; }}export default createStore(counterReducer)
    Copy the code
    import { Component } from 'react'
    import store from './store'
    
    export default class ReduxPage extends Component {
      componentDidMount() {
        this.unsubscribe = store.subscribe(() = > {
          this.forceUpdate(); })}// Unsubscribe
      componentWillUnmount() {
        if (this.unsubscribe) {
          this.unsubscribe()
        }
      }
    
      // Send events
      add = () = > {
        store.dispatch({ type: 'ADD'.payload: 100 })
      }
    
      minus = () = > {
        store.dispatch({ type: 'MINUS'})}render() {
        return (
          <div>
            <h3>ReduxPage</h3>
            <div>{store.getState()}</div>
            <button onClick={this.add}>add</button>
            <button onClick={this.minus}>minus</button>
          </div>)}}Copy the code
  • Explain redux API

    • createStorecreatestoreTo receivereducer, returns an object
    • reducerInitialize and modify state functions, pure functions
    • getStateGet status value
    • dispatchSubmit updates, receiveaction payload
    • subscribeChange the subscription

Ii. Basic function realization of My-Redux

  • Define the createStore function to implement getState Dispatch SUBSCRIBE apis:

    // createStore.js
    export default function createStore(reducer) {
      let currentState; // Define current state
      let currentListeners = []; // Define the listener function
    
      // getState api
      function getState() {
        return currentState;
      }
      
      // dispatch api
      function dispatch(action) {
        currentState = reducer(currentState, action);
    
        currentListeners.forEach(listener= > listener());
      }
    
      // subscribe api
      function subscribe(listener) {
        currentListeners.push(listener);
      }
    
      return {
        getState,
        dispatch,
        subscribe
      }
    }
    Copy the code
  • Get the initial value

    // createStore.js
    export default function createStore(reducer) {...// Trigger to get the initial value
      dispatch({ type: '@my-redux-xxxx' })
      
      return{... }}Copy the code
  • unsubscribe

    // createStore.js
    export default function createStore(reducer) {...// subscribe api
      function subscribe(listener) {
        currentListeners.push(listener);
    
        return () = > {
          const index = currentListeners.indexOf(listener);
          currentListeners.splice(index, 1); }}return{... }}Copy the code

Three, asynchronous implementation

  • Middleware Schematic Diagram

  • Use:

    // store.js
    import { createStore, applyMiddleware, combineReducers } from 'redux'
    import thunk from 'redux-thunk'
    import logger from 'redux-logger'
    
    export const counterReducer = (state = 0, { type, payload = 1 }) = > {
      switch (type) {
        case "ADD":
          return state + payload;
        case "ASYNC-ADD":
          return state + payload;
        case "MINUS":
          return state - payload;
        default:
          returnstate; }}export default createStore(
      combineReducers({
        counter: counterReducer,
      }),
      applyMiddleware(thunk, logger)
    )
    
    
    // pageJsx
    asyncAdd = () = > {
      store.dispatch((dispatch, getState) = > {
        setTimeout(() = > {
          dispatch({ type: 'ASYNC-ADD'.payload: 50})},1000)})}Copy the code
  • Implementation:

    // store.js
    // import { createStore, applyMiddleware, combineReducers } from 'redux'
    import { createStore, applyMiddleware } from './createStore'
    // import thunk from 'redux-thunk'
    import thunk from './thunk'
    // import logger from 'redux-logger'
    import logger from './logger'
    
    
    export const counterReducer = (state = 0, { type, payload = 1 }) = > {
      switch (type) {
        case "ADD":
          return state + payload;
        case "ASYNC-ADD":
          return state + payload;
        case "MINUS":
          return state - payload;
        default:
          returnstate; }}export default createStore(
      counterReducer,
      applyMiddleware(thunk, logger)
    )
    Copy the code
    // createStore.js
    import applyMiddleware from './applyMiddleware'
    
    function createStore(reducer, enhancer) {
      // enhancer
      if (enhancer) {
        return enhancer(createStore)(reducer)
      }
      
      ...
    }
    Copy the code
    // applyMiddleware.js
    function compose(. funcs) {
      if (funcs.length === 0) {
        return arg= > arg
      }
    
      if (funcs.length === 1) {
        return funcs[0]}// fn aggregate function fn2 current function
      return funcs.reduce((fn, fn2) = > {
        return (. args) = >fn(fn2(... args)) }) }export default function applyMiddleware(. middlewares) {
      // console.log(middlewares);
    
      return createStore= > reducer= > {
        // Todo strengthens dispatch
        const store = createStore(reducer);
        let dispatch = store.dispatch
    
        const middlewareChain = middlewares.map(middleware= > middleware({
          getState: store.getState,
          dispatch: (action, ... args) = >dispatch(action, ... args) }))// Execute the middleware functions sequentially
        // Enhanced dispatchdispatch = compose(... middlewareChain)(store.dispatch)return {
          ...store,
          dispatch
        }
      }
    }
    Copy the code
    // thunk.js
    export default function thunk({ getState, dispatch }) {
      return next= > action= > {
        if (typeof action === 'function') {
          return action(dispatch, getState)
        }
        return next(action)
      }
    }
    Copy the code
    // logger.js
    export default function logger({ getState, dispatch }) {
      return next= > action= > {
        console.log('=> prevState --------', getState())
        const returnVal = next(action)
        console.log('=> nextState --------', getState())
        return returnVal
      }
    }
    Copy the code

Four, CombineReducer implementation

  • Implementation:

    // store.js
    // import { createStore, applyMiddleware, combineReducers } from 'redux'
    import { createStore, applyMiddleware, combineReducers } from './createStore'
    // import thunk from 'redux-thunk'
    import thunk from './thunk'
    // import logger from 'redux-logger'
    import logger from './logger'
    
    export const counterReducer = (state = 0, { type, payload = 1 }) = > {
      switch (type) {
        case "ADD":
          return state + payload;
        case "ASYNC-ADD":
          return state + payload;
        case "MINUS":
          return state - payload;
        default:
          returnstate; }}export const counterReducer2 = (state = {num: 0}, { type, payload = 1 }) = > {
      switch (type) {
        case "ADD2":
          return{... state,num: state.num + payload};
        default:
          returnstate; }}export default createStore(
      combineReducers({
        counter: counterReducer,
        counter2: counterReducer2,
      }),
      applyMiddleware(thunk, logger)
    )
    Copy the code
    // combineReducers.js
    export default function combineReducers(reducers) {
      return (state = {}, action) = > {
        const nextState = {}
        let hasChanged = false
        for (let key in reducers) {
          constreducer = reducers[key] nextState[key] = reducer(state[key], action) hasChanged = hasChanged || nextState[key] ! == state[key] }return hasChanged ? nextState : state
      }
    }
    Copy the code

Five, the harvest

  1. How is Redux used?
  2. What is redux? What are its properties?
  3. What is the nature of store State?
  4. What is the nature of Reducer?
  5. Middleware principles?
  6. How to read the source code? Master encapsulated thinking?

Experience Demo on Github

Github.com/zhuyuanmin/…

Criticism is welcome 👏🏻