Author: HerryLo

In this paper, permanent links: https://github.com/AttemptWeb…

Redux is a JavaScript state container that provides predictable state management.

React + react-redux is often used in real applications. This represents a fundamental concept of front-end development today, the separation of data and view.

Redux came into being, and there are other state management libraries, such as Flux, Elm, etc., but of course, we only parse Redux here.

# story to create a Store

To create a Store object for Redux, you need to call the combineReducers and createStore functions. Middleware is not included as explained below.

const reducer = combineReducers({ home: homeNumber, number: AddNumber}) const store = createStore(reducer) $reduxStore = storeCopy the code

# combineReducers function

First call combineReducers function, pass in a number of reducer functions as parameters, source code is as follows:

Function combineReducers(reducers) {//...... Omit return function combination(state = {}, action) {let hasChanged = false const nextState = {} for (let I = 0; i < finalReducerKeys.length; I ++) {// finalReducerKeys is the key value passed into the Reducers object const Key = finalReducerKeys[I] // finalReducers is equivalent to Reducers const Reducer = finalReducers[key] const previousStateForKey = state[key] Call the combination function, Const nextStateForKey = Reducer (previousStateForKey, action) nextState[key] = nextStateForKey // hasChanged = hasChanged || nextStateForKey ! == previousStateForKey } // hasChanged = hasChanged || finalReducerKeys.length ! Keys (state).length // return nextState}} https://github.com/reduxjs/redux/blob/master/src/combineReducers.ts#L139Copy the code

The above code is actually quite simple, the combineReducers function runs and returns a new combination function. The combination function returns an object with all state mounted. When the combination function is called, it is essentially a circular call to the reducer function passed in, returning the state object. Pass the combination function as an argument to the createStore function.

# createStore function

function createStore(reducer, preloadedState, Reducer) {// reducer -> combination let currentReducer = reducer all state attributes, If (typeof preloadedState === 'function' && typeof Enhancer === 'undefined') {// Second argument is a function, PreloadedState = undefined} if (typeof enhancer! == 'undefined') {// If middleware exists, createStore is passed into the middleware function, enhancer is called, and return ends. return enhancer(createStore)(reducer, PreloadedState)} function dispatch(action) {// currentReducer -> Combination currentState = CurrentReducer (currentState, action)} ActionTypes.INIT }) const store = ({ dispatch: dispatch, subscribe,s getState, replaceReducer, [$$observable]: Observables} return store} / / source address: https://github.com/reduxjs/redux/blob/master/src/createStore.ts#L60Copy the code

Reducer is the incoming combination function, preloadedState is the initialized state(not very useful), enhancer is the middleware, without the third parameter enhancer, and the second parameter preloadedState is a function. PreloadedState is assigned to enhancer.

Call the Dispatch function to initialize, and currentReducer is passed in the combination function. As mentioned above, call the Combination function is actually a circular call to the Reducer function. All state objects are mounted on the internal variable currentState. When middleware enhancer is present, createStore is passed to the middleware function, the enhancer function is called, and the return is completed, as discussed below.

Create a store object that exposes the following method:

Const store = ({// Distribute the action, which is the only way to trigger a state change. dispatch: Dispatch as dispatch <A>, // subscribe, // store state getState, // Replace the reducer replaceReducer} return store currently used to calculate stateCopy the code

The Dispatch function triggers the action and calls the Reducer function to modify the state. The SUBSCRIBE function listens for changes in state. The getState function gets all the states. The replaceReducer function replaces the reducer function used to calculate state.

throughcombineReducersThe reducer function is merged with the reducer function and returns a new functioncombinationThis function loops through the Reducer function, returning all state. Pass in the new function as an argumentcreateStoreFunction, which is passed in internally via dispatch initializationcombination, state generates, and returns the store object

# redux middleware

Better read the above, then look at the middleware part!! The analysis of middleware is as follows:

Redux-thunk is just one type of Redux middleware, and it is a common middleware. The Redux-Thunk library allows you to write asynchronous logic that interacts with stores.

import thunkMiddleware from 'redux-thunk' const reducer = combineReducers({ home: homeNumber, number: AddNumber}) const store = createStore(Reducer, applyMiddleware(thunkMiddleware))Copy the code

CreateStore supports three arguments. If the second argument, preloadedState, is a function and the third argument, enhancer, is not present, preloadedState will be assigned to enhancer.

Using the Redux-Thunk middleware as an example, here is the code for the thunkMiddleware function:

// A partial conversion to ES5 code, running the Middleware function returns a new function like this:  return ({ dispatch, Return function (next) {return function (action) {// redux-thunk core if (typeof) action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; }; } / / source address: https://github.com/reduxjs/redux-thunk/blob/master/src/index.jsCopy the code

Github: redux-Thunk source code is very simple

, allows action to be a function, and supports argument passing, otherwise the calling method remains the same.

# applyMiddleware function

Return enhancer(createStore)(reducer, preloadedState) is equivalent to return applyMiddleware(thunkMiddleware, )(createStore)(reducer, preloadedState)Copy the code

Redux’s middleware, starting with the applyMiddleware function, is primarily designed to handle store dispatches.

Export Default Function applyMiddleware(... middlewares) { return (createStore) => (reducer, ... Args) => {const store = createStore(reducer,... args) const middlewareAPI = { getState: store.getState, dispatch: (action, ... args) => dispatch(action, ... Args)} // Run the middleware function, passing the middlewareAPI as a parameter, and // middleware corresponding to the redux-Thunk library core code above. Middlewares.map (Middleware => Middleware API) const chain => Middleware. Pass all middleware into compose and return a new dispatch dispatch = compose(... Chain)(store.dispatch) // As usual returns a store object, dispatch has already been processed return {... Store, dispatch}}} / / source address: https://github.com/reduxjs/redux/blob/master/src/applyMiddleware.ts#L55Copy the code

The applyMiddleware function takes multiple middlewares parameters and returns a store object. The Store object is created by createStore, the middlewareAPI object is mounted with getState and Dispatch, and the Middlewares middleware is looped through, passing the middlewareAPI as a parameter to each middleware. At the end of the loop, we get an array of all the middleware’s new return functions and assign them to the variable chain.

// chain after traversal, // Next is dispatch chain = [function (next) {return function (action) {if (typeof action ===) 'function') {return action(dispatch, getState, extraArgument);} return next(action);};},... more middleware]Copy the code

# compose function

Dispatch = compose(... chain)(store.dispatch)Copy the code

Compose’s main purpose is to iterate through all the middleware functions and aggregate them back into a single Dispatch function.

// compose function return chain.reduce((a, b) =>{return (... args)=> { return a(b(... args)) } }Copy the code

Chain is an array of middleware functions. For the specific internal structure, see 👆. Let’s analyze the call logic of compose function.

// chain analogy is [fn1, fn2, fn3, fn4] [Fn1, fn2, fn3, fn4]. Reduce ((a, b) =>{return (... args)=> { return a(b(... args)) } }Copy the code

The call process is as follows:

cycle

A value

B value

The value returned

First cycle

fn1

fn2

(… args)=> fn1(fn2(… args))

Second cycle

(… args)=> fn1(fn2(… args))

fn3

(… args)=> fn1(fn2(fn3(… args)))

Third cycle

(… args)=> fn1(fn2(fn3(… args)))

fn4

(… args)=> fn1(fn2(fn3(fn4(… args))))

After the compose process, the final return value is (… args) => fn1(fn2(fn3(fn4(… Args)))), the arg of which is the store.dispatch function. Finally, we assign the return function to Dispatch, which is the dispatch function we need. If there is only one middleware, it will return directly.

The main purpose of the middleware is to modify the Dispatch function to return a new Dispatch function processed by the middleware

# redux use

React -redux+react;

window.$reduxStore = store

store.dispatch(action);

let { aState } = store.getState()
Copy the code

Mount it directly under the Window object, so it can be used with any front-end framework. This is definitely not elegant. I’ll talk about react-Redux later.

This call to the store.dispatch function is essentially a repeat of the call to the Reducer function, which is saved to the internal variable currentState of the createStore function. The currentState variable is returned using the store.getState function to get all the states.

# end:

It’s a bit too much to sum up

1. Redux create Store: Combine the Reducer function with the combineReducers function and return a new reducer function combination (this function iterates through the Reducer function and returns all state). This new function is passed as an argument to the createStore function, which initializes the incoming combination through dispatch, generates state, and returns a Store object.

The main purpose of the middleware is to modify the Dispatch function and return a new Dispatch function that is processed by the middleware

Here is the end of the analysis, Redux is really very functional, full of functional programming ideas, very modular, with strong versatility, feel very good 👍👍

See more blog posts:

Personal gold digging more articles link jump;

GitHub blog project links to more articles jump;