createStore

This createStore function needs to return an object containing the following attributes:

  • dispatch: Distribute actions to change data
  • getState: Gets the state in the current repository
  • subscribe: Registers a listener and fires after the action is issued. And returns a function that cancels listening
  • replaceReducerReplace the current reducer in the repository
  • Symbol("observable"): built-in function to implement observer mode (not implemented yet)

Code implementation:

/** * create repository *@param {function} reducer 
 * @param {any} DefaultState specifies the defaultState */
export default function createStore(reducer, defaultState) {
    // Simply verify that reducer is a function
    if (typeofreducer ! = ='function') {
        throw new TypeError(`The first parameter reducer must be a function`)}let currentReducer = reducer Reducer is currently in use
    let currentState = defaultState // Current status value
    const subscribers = [] // Array of listeners

    function dispatch(action) {
        // Verify the action type
        if(! _isPlainObject(action)) {throw new TypeError(`The required parameter action must be a "Plain Object"`)}if (action.type === undefined) {
            throw new TypeError(`The required parameter action must have a property of "type"`)
        }
        currentState = currentReducer(currentState, action)
        // Execute all listeners
        subscribers.forEach(subscriber= > {
            subscriber()
        })
    }

    function getState() {
        return currentState
    }

    // Add a listener
    function subscribe(subscriber) {
        subscribers.push(subscriber)
        let isRemoved = false // Determine if it has been removed
        return () = > {
            if (isRemoved) return
            const index = subscribers.indexOf(subscriber)
            subscribers.splice(index, 1)
            isRemoved = true}}function replaceReducer(newReducer) {
        // Simply verify that reducer is a function
        if (typeofnewReducer ! = ='function') {
            throw new TypeError(`The first parameter reducer must be a function`)
        }
        currentReducer = newReducer
    }

    // When the warehouse is created, a dispatch action needs to be called to complete state initialization
    dispatch({
        type: `@@redux/INIT${_getRandomStr(7)}`
    })

    return {
        dispatch,
        getState,
        subscribe,
        replaceReducer
    }
}
Copy the code

Auxiliary functions involved:

/** * Check whether this object is a flat object *@param {Object} O Target object *@returns boolean* /
function _isPlainObject(o) {
    if (typeofo ! = ='object') {
        return false
    }
    return Object.getPrototypeOf(o) === Object.prototype
}

/** * returns a string of the specified length, for example: 'f.A. 4.d.7' *@param {number} Len string length */
function _getRandomStr(len = 7) {
    // Convert to base 36, i.e., 26 letters + 10 digits
    return Math.random().toString(36).substr(2, len).split(' ').join('. ')}Copy the code

bindActionCreators

By passing two arguments :(1) action creates the function or the object that action creates the function; (2) the dispatch function

To get the enhanced action create function or the action create function object

/** * enhances the action creation function *@param {*} actionCreators 
 * @param {*} dispatch 
 */
export default function bindActionCreators(actionCreators, dispatch) {
    if (typeof actionCreators === 'function') {
        return _getAutoDispatchActionCreator(actionCreators, dispatch)
    } else if( actionCreators ! = =null &&
        typeof actionCreators === 'object'&&!Array.isArray(actionCreators)
    ) {
        const res = {}
        for (const key in actionCreators) {
            if (Object.hasOwnProperty.call(actionCreators, key)) {
                const actionCreator = actionCreators[key]
                if (typeof actionCreator === 'function') {
                    res[key] = _getAutoDispatchActionCreator(actionCreator, dispatch)
                }
            }
        }
        return res
    } else {
        throw new TypeError(`The first parameter of actionCreators must be an "object" or "function" which means action creator`)}}/** * get the creation function that automatically distributes the action *@param {*} actionCreators 
 * @param {*} dispatch 
 */
function _getAutoDispatchActionCreator(actionCreators, dispatch) {
    return (. args) = > {
        constaction = actionCreators(... args) dispatch(action) } }Copy the code

combineReducers

Function: Assemble reducers and return a Reducer. Data is represented by an object, and the attribute name of the object is consistent with the parameter object passed

When it is called to merge the reducers, each Reducer will distribute two special types of actions to ensure that the returned state is not undefined

The implementation is as follows:

/** * Merge reducers *@param {Object}} reducers
 * @return {Funtion} reducer* /
export default function combineReducers(reducers) {
  
  _validateReducers(reducers)
  
  return function (state = {}, action) {
    const newState = {}
    for (const key in reducers) {
      if (Object.hasOwnProperty.call(reducers, key)) {
        const reducer = reducers[key]
        newState[key] = reducer(state[key], action)
      }
    }
    return newState
  }
}

/** * Verify reducers *@param {*} reducers* /
function _validateReducers(reducers) {
  if (
    typeofreducers ! = ='object' ||
    reducers === null ||
    Array.isArray(reducers)
  ) {
    throw new TypeError(`reducers must be an "object"`)}if(! isPlainObject(reducers)) {throw new TypeError(`reducers must be a "plain object"`)}Verify that each reducer return result is undefined
  for (const key in reducers) {
    if (Object.hasOwnProperty.call(reducers, key)) {
      const reducer = reducers[key]
      let state = reducer(undefined, {
        type: `@@redux/INIT${_getRandomStr(7)}`
      })
      if (state === undefined) {
        throw new TypeError(`reducer returns state cannot be undefined`)
      }
      state = reducer(undefined, {
        type: `@@redux/PROBE_UNKNOWN_ACTION${_getRandomStr(7)}`
      })
      if (state === undefined) {
        throw new TypeError(`reducer returns state cannot be undefined`)}}}}Copy the code