You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The upper part is the English version, and the lower part is the Chinese version, with the same content. If there are any wrong, or you have anything hard to understand, pls feel free to let me know.many thx.
Overview
Analyze the principle and source code of Redux
1. Redux data flow
Action: plain javascript object,define what happened
Reducer: fn(state,action), return new state
State: {},define state of ui component
Store: manage action and reducer and state
export default function createStore(reducer, preloadedState, enhancer) {
// first,validate passed params
...
// define internal variables
let currentReducer = reducer
let currentState = preloadedState
let currentListeners = []
let nextListeners = currentListeners
let isDispatching = false
//copy currentListeners into nextListeners
//subcribe/unsubcribe uses nextListeners,dispatch uses currentListeners
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice()
}
}
//read state
function getState() {
...
return currentState
}
//triggered when state changes
function subscribe(listener) {
...
//add into nextListeners
nextListeners.push(listener)
return function unsubscribe() {
//remove the listener from nextListeners
isSubscribed = false
ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
currentListeners = null
}
}
function dispatch(action) {
//first,validate passed params)
...
try {
isDispatching = true
//exec reducer
currentState = currentReducer(currentState, action)
} finally {
isDispatching = false
}
//triger every listener
const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
return action
}
//1. accept a reducer to replace the current reducer
//2. then execute dispatch({ type: ActionTypes.REPLACE}) to initialize the state of the store
function replaceReducer(nextReducer) {
...
currentReducer = nextReducer
dispatch({ type: ActionTypes.REPLACE })
}
dispatch({ type: ActionTypes.INIT })
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable,
}
}
dispatch (publish), getState (get state), subscribe (listen) three core APIs
The unsubscribe method is the return value of the subscribe method
subscribe: add callback function to nextListeners, unsubscribe: delete from nextListeners
dispatch: execute reducer->execute each listener
A state update process of redux: dispatch trigger -> execute reducer -> execute all listeners (executing a subscribe will add a listener to the nextListeners array)
//After the action is executed, dispatch is called automatically
function bindActionCreator(actionCreator, dispatch) {
return function () {
return dispatch(actionCreator.apply(this, arguments))
}
}
export default function bindActionCreators(actionCreators, dispatch) {
...
const boundActionCreators = {}
const boundActionCreators = {}
//iterate the object and generate a function that wraps the dispatch according to the corresponding key
for (const key in actionCreators) {
const actionCreator = actionCreators[key]
if (typeof actionCreator === 'function') {
boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
}
}
return boundActionCreators
}
bind actionCreator and dispatch together
Example using bindActionCreators
const mapStateToProps = (state: any) => ({
todos: state.todos
})
const mapDispatchToProps = (dispatch: Dispatch) =>
bindActionCreators(
todoActions,
dispatch
)
export default connect(mapStateToProps, mapDispatchToProps)(App)
// using in business code as bellow
this.props.todo({})
//note: only use mapDispatchToProps and pass in the Actions object, the effect is the same as above, so not used much
const mapDispatchToProps = {
...todoActions
}
applyMiddleware.js, compose.js are placed below for separate analysis
4. Redux middleware
4.1 Invoke flow after adding middleware
Middleware is used to handle side effects, such as asynchronous requests
4.2 How to use
// add a middleware
const store = createStore(reducer, applyMiddleware(middlewareA));
export default function applyMiddleware(...middlewares) {
return (createStore) => (...args) => {
const store = createStore(...args)
let dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' +
'Other middleware would not be applied to this dispatch.'
)
}
//define the parameters passed to the middleware: {getState,dispatch}
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args),
}
//pass to each middleware: {getState,dispatch}
const chain = middlewares.map((middleware) => middleware(middlewareAPI))
//pass to each middleware: {store.dispatch}
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch,
}
}
}
The upper part is the English version, and the lower part is the Chinese version, with the same content. If there are any wrong, or you have anything hard to understand, pls feel free to let me know.many thx.
Overview
1. Redux data flow
2. Invoke flow
3. Source code
source code
3.1 Entrance
index.js source code
3.2 createStore.js
createStore source code
3.3 combineReducers.js
combineReducers source code
3.4 bindActionCreators.js
bindActionCreators source code
Example using bindActionCreators
4. Redux middleware
4.1 Invoke flow after adding middleware
4.2 How to use
4.3 Source code
4.3.1 applyMiddleware.js
applyMiddleware source code
4.3.2 compose.js
compose source code
4.4 Simplified version
The effect of compose
4.5 Example building middleware
Simplified version
Transform into a shape that conforms to redux middleware
The following is the Chinese version, the same content as above
Overview
1. Redux的数据流
2. 调用流程
3. 源码
源码地址
3.1 入口
index.js 源码
3.2 createStore.js
createStore 源码
3.3 combineReducers.js
combineReducers 源码
3.4 bindActionCreators.js
bindActionCreators 源码
举例使用bindActionCreators
4. redux middleware
4.1 增加中间件后的调用流程
4.2 如何使用
4.3 源码
4.3.1 applyMiddleware.js
applyMiddleware 源码
4.3.2 compose.js
compose 源码
4.4 简化写法
compose 的效果
4.5 举例构建一个middleware
简化写法
改造成符合redux middleware的代码形状
The text was updated successfully, but these errors were encountered: