Redux core concepts

  • A single store can only survive getState() and cannot be modified directly
  • The state can only be changed by triggering action
  • Use the pure function reducers to describe how actions change state

The whole redux implementation is around the above three points for implementation, the entire source code is not large, after understanding the core concept to see the source code will find the structure logic is very clear, the code is also very comprehensive annotations, this article will be in accordance with how to achieve the core concept to read the source code. (You already know how to use Redux by default)

Reducer

We first look at the use of Reducer in REdux to further understand the role of Reducer

currentState = currentReducer(currentState, action)
Copy the code

This is the only place that redux uses reducer. In the dispatch function, the old state and the actions of dispatch are passed in to obtain the new state, which is exactly the same as redux’s description of reducer. Therefore, when we compile the reducer function, we must strictly follow the specification of REdux to write a pure function, so as to ensure that your state changes can be easily tracked.

Action

All our actions are managed through Dispatch, so we are talking about the implementation of Dispatch directly. The interesting thing is that there is actually a synchronous lock isDispatching in REdux. In this way, many logic in handling concurrency are avoided, for example, concurrency may lead to the risk of reading dirty data. You didn’t know redux had such a design until you looked at the source code.

functionDispatch (action) {// Some errors are omitted. The code for checking aciton summarizes that aciton must be an object and have onetypeAttribute // isDispatching is similar to synchronous locks, ensuring the atomicity of the state in each modificationif (isDispatching) {
      throw new Error('Reducers may not dispatch actions.')
    }
    try {
      isDispatching = trueCurrentState = currentReducer(currentState, Action)} finally {// Unlocking ispeer =falseConst listeners = (currentListeners = nextListeners)for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }

    return action
  }
Copy the code

Store

The most important part of redux is createStore, which stores state and combines reducer and Action.

// Receive the function returned by reducer after adding middleware to the initial state applyMiddlewareexport default functionCreateStore (Reducer, preloadedState, enhancer) {// Resolve the case where we do not pass preloadedState and the second parameter is enhancerif (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preloadedState
    preloadedState = undefined
  }

  if(typeof enhancer ! = ='undefined') {
    if(typeof enhancer ! = ='function') {
      throw new Error('Expected the enhancer to be a function.'} // What enhancer does in applyMiddleware is add middleware to enhance dispatch capabilitiesreturn enhancer(createStore)(reducer, preloadedState)
  }

  if(typeof reducer ! = ='function') {
    throw new Error('Expected the reducer to be a function.'} //store transitionsletCurrentReducer = reducer // Our state treelet currentState = preloadedState
  let currentListeners = []
  let nextListeners = currentListeners
  let isDispatching = false. // Return the store object and the APIreturn{// trigger aciton to use dispatch, // add state change callback with subscribe, // obtain state getState, // replaceReducer replaceReducer, [$$observable]: observable
  }
Copy the code

conclusion

The entire Redux source code only takes about an hour to read, but the overall harvest is huge. We can see that the Redux authors started with core concepts and turned them into tools.