Import {createStore} from ‘redux’; import {createStore} from ‘redux’; How the introduced createStore is implemented in Redux and what its functionality is. We all know that the most common use of createStore is to pass a reducer to return a store. In conjunction with React, we often pass a reducer entry file to createStore to get a store.

Redux accepts a reducer and an initial state and returns a Store.

 * @param {Function} reducer 
 * @param {any} [initialState]
 * @returns {Store}
 
export default function createStore(reducer, initialState) {
  invariant(
    typeof reducer === 'function'.'Expected the reducer to be a function.'
  );

  var currentReducer = reducer;
  var currentState = initialState;
  var listeners = [];
  var isDispatching = false;

  function getState() {
    returncurrentState; }... }Copy the code

Let’s look at the implementation. First of all, weyl should be a tool function with error notification. Without delving into the internal implementation logic, weyl continues to see four assignment statements, each of which means “reducer”, “state”, “listener”, and “reducer”. Whether to dispatch the Falg. We then define a function called getState, which we’re all familiar with, to return the current state.

Let’s go ahead and write the following explanation directly in code, which feels a little more intuitive

  /* * @returns {Function} The reducer used by the current store. */
  function getReducer() {
    return currentReducer;
  }
  / * from the value returned from this function definition should be can see come out, the role of the main reducer is returned to the store, but our chances of development at ordinary times when directly use this function should be little, and now this API has also been redux removed. * /
Copy the code
 /* * @param {Function} listener A callback to be invoked on every dispatch. * @returns {Function} A function to remove this change listener. */
  function subscribe(listener) {
    listeners.push(listener);

    return function unsubscribe() {
      var index = listeners.indexOf(listener);
      listeners.splice(index, 1);
    };
  }
  /* * The subscript here accepts a listener callback function that returns a function that can cancel the listener function. The function unsubscribe does two things internally: find the current listeners listening for the function's index position in the Listeners array and remove it from the listeners array
Copy the code

Let’s take a look at one of the more critical functions, dispatch

/*
* @param {Object} action
* @returns {Object}
*/
function dispatch(action) {
    invariant(
      isPlainObject(action),
      'Actions must be plain objects. Use custom middleware for async actions.'
    );
    
    // Determine if the action is a normal object, and return an error message if it is not

    invariant(
      isDispatching === false.'Reducers may not dispatch actions.'
    );
    
    Check whether the current Reducer is dispatching

    try {
      isDispatching = true;
      currentState = currentReducer(currentState, action);
    } finally {
      isDispatching = false;
    }
    // Execute the current dispatch

    listeners.slice().forEach(listener= > listener());
    // Executes the listener function bound to this action
    
    return action;
  }
/* * Here we can see that the dispatch function accepts an action object and returns an object,Copy the code
/** * Replaces the reducer currently used by the store to calculate the state. * * You might need this if your app implements code splitting and you want to * load some of the reducers dynamically. You might also need this if you * implement a hot reloading mechanism for Redux. * * @param {Function} nextReducer The reducer for the store to use instead. * @returns {void} */
function replaceReducer(nextReducer) {
  currentReducer = nextReducer;
  dispatch({ type: ActionTypes.INIT });
}
Copy the code

From his comments we know that this function replaces the reducer of the current store and calculates the state after the reducer. This function is often used when your application needs to split code or you want to load the reducer dynamically.

👌 I think we’ve seen enough code now to explain the inner workings of the following code. Let’s take a look

import { createStore } from 'redux';

function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT':
    return state + 1;
  case 'DECREMENT':
    return state - 1;
  default:
    returnstate; }}let store = createStore(counter);


store.subscribe((a)= >
  console.log(store.getState())
);


store.dispatch({ type: 'INCREMENT' });
/ / 1
store.dispatch({ type: 'INCREMENT' });
/ / 2
store.dispatch({ type: 'DECREMENT' });
/ / 1
Copy the code

First we define a counter function, which is a Reducer, and then pass this reducer to createStore. Let’s see what happens. Here we simply give the incoming reducer to currentReducer. This generates a store, which is then used to register a listener function. In registering a listener, we push a listener into the listener array and return a function that can be unregistered. So we’re going to trigger the dispatch, and we’re going to see what happens when we dispatch, and we’re going to check if the action that’s passed in is a normal object, which is an object, and we’re going to go down and see if the dispatch is happening, and we’re not, and we’re going to go down, and we’re going to do currentReducer, So that’s our counter function, and the action that’s passed in is the one that’s passed in at dispatch, gets a currentState and then loops through the listener function, we only have one, which prints out the currentState and returns the action, I’m guessing that the action we passed in should be used for the next dispatch.

This concludes the first part of the redux documentation, and in the next article I’ll follow the redux documentation to see how the rest of the REdux API works.