createStore
Generally speaking, I look at the source code of a library, looking first at the parameters of the corresponding method, then at the corresponding return, and then at the implementation of the code.
The createStore method returns an object that exposes five methods, four of which are commonly used:
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
Copy the code
Looking at the beginning of the source code, we see that createStore can pass in two triadic parameters:
export default function createStore(reducer, preloadedState, enhancer)
Copy the code
The first reducer parameter must be passed and must be a function, or Redux returns a reducer
if(typeof reducer ! = ='function') {
throw new Error('Expected the reducer to be a function.')}Copy the code
If the second argument, preloadedState, is passed and not a function, then preloadedState is stored in the internal variable currentState, which is the default State we gave State
If preloadedState is a function, assign preloadedState to enhancer
if (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.'} // Run enhancer. Enhancer is a group of middlewarereturn enhancer(createStore)(reducer, preloadedState)
}
if(typeof reducer ! = ='function') {
throw new Error('Expected the reducer to be a function.')}Copy the code
Three important variables are saved in this method:
let currentReducer = reducer
let currentState = preloadedState
let currentListeners = []
Copy the code
- CurrentReducer saves all Reducer files
- CurrentState is where all the state data is stored and is the only object where Redux manipulates the data
- CurrentListeners save listeners to Redux State subscriptions
Now that we know the three main internal variables Redux can control, we will learn how to manipulate them based on the five methods revealed by createStore
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
Copy the code
Dispatch (remove verification code)
function dispatch(action) {
try {
isDispatching = true// Call Reduce to process the action, passing in the original state each time. Returns the updated States currentState = currentReducer(currentState, Action)} finally {isDispatching =falseConst listeners = (currentListeners = nextListeners)for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
return action
}
Copy the code
We first need to pass an action parameter to tell the action Object that we need to do. The action can only be an Object and must contain the Type field
if(! isPlainObject(action)) { throw new Error('Actions must be plain objects. ' +
'Use custom middleware for async actions.')}if (typeof action.type === 'undefined') {// Must contain **Type** throw new Error('Actions may not have an undefined "type" property. ' +
'Have you misspelled a constant? ')}Copy the code
We call the internal variable currentReducer to handle the corresponding action initiated
currentState = currentReducer(currentState, action)
Copy the code
CurrentReducer is a function that takes two arguments: currentState and Action.
The value returned by currentReducer is assigned to currentState, as is known from the analysis of the argument passed in to createStore, PreloadedState can only be given to Object, so currentReducer function returns to Object.
From this line of code we can conclude:
Reducer is a function that processes currentState based on actions and returns a new currentState function
const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
Copy the code
As we can see from the above code, when updating state, we need to iterate over all the listeners to let them know the information of state change
The subscribe (subscription)
Subscribe is a message subscription
function subscribe(listener) {
let isSubscribed = true
ensureCanMutateNextListeners()
nextListeners.push(listener)
return function unsubscribe() {
if(! isSubscribed) {return
}
isSubscribed = false
ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
}
}
Copy the code
Very simple code, the listener is passed in as a subscriber method,
nextListeners.push(listener)
Copy the code
Store the listener in an array of internal variables. Returns an unsubscribe method that unsubscribes
Listeners are unsubscribed whenever they are removed from the arrayCopy the code
GetState (getState)
function getState() {
return currentState
}
Copy the code
Very simple, just return the internal variable currentState
ReplaceReducer replacement (reducer)
function replaceReducer(nextReducer) {
currentReducer = nextReducer
dispatch({ type: ActionTypes.REPLACE })
}
Copy the code
Replace the current reducer.
conclusion
- First we need to create a store by calling the createStore method
let store = createStore(reducer, preloadedState)
Copy the code
Reducer is a function and two parameters must be passed, the first being state and the second an action
- Trigger store.dispatch(Action) with related events to change the state
This action must have a type attribute
- Store. Subscribe (listener)
- Get the latest state(store.getState()) in the listener and proceed accordingly
Redux examples