如何实现一个redux?
确切来说应该是js状态管理库, redux现在常用redux-toolkit,以后有机会总结。
-
什么是reducer?
reducer 是一个纯函数,传入旧的state和action,返回新的state。(可以类比js reduce函数)。
JavaScript
const reducer = (previousState, action) => newState
- Redux基本概念
- React Component
- Action Creators
- Store
- Reducers
- Redux 基本使用
JavaScript
export default function ReduxPage(){
const [state, setState] = useState(store.getState().count);
const add = () => {
store.dispatch({type: 'ADD'})
}
const minus = () => {
store.dispatch({type: 'Minus'})
}
useEffect(() => {
const unsubscribe = store.subscribe(() => {
setState(store.getState().count);
});
return () => unsubscribe();
}, []);
return(
<div>
<h3>ReduxPage</h3>
<p>{state}</p>
<button onClick={add}>add</button>
</div>
)
}
JavaScript
function countReducer(state = 0, action){
switch(action.type){
case "ADD":
return state + 1
case "Minus":
return state - 1
default:
return state
}
}
export const store = createStore(countReducer)
- Redux基本实现
createStore -- 发布订阅模式
接收什么?
目前是一个reducer。(还可以加入中间件)
返回什么?
{getState,dispatch,subscribe}三个方法。
JavaScript
export default function createStore (reducer) {
let currentState
let currentListeners = []
function getState(){
return currentState
}
function dispatch(action){
currentState = reducer(currentState,action)
currentListeners.forEach(listener=>{
listener()
})
}
function subscribe(listener){
currentListeners.push(listener)
return () => {
const index = currentListeners.indexOf(listener)
currentListeners.splice(index,1)
}
}
dispatch({type:'ADADAD'})
return {getState,dispatch,subscribe}
}
思考: 为什么要dispatch({type:'ADADAD'})
,其实是拿到初始状态(本例子中的state = 0),触发default:return state
,不要忘记加。
-
rudux中间件 想要增强redux的功能,如异步(redux-thunk),日志打印(redux-logger)等,可以使用中间件来增强一般的redux,以后有机会总结一下如何实现。
-
管理多个reducer
在一个项目中,可能会有很多不同的状态需要管理,也就是有很多reducer, 那么我们需要将多个reducer合并成一个reducer。
怎么使用呢?
JavaScript
export const store = createStore(
combineReducers({count:countReducer,和其他reducer}),
applyMiddleware(thunk,logger)) //这个是中间件,暂时可以不管它
如何实现一个combineReducer?
先考虑接受什么参数? -- 一个对象,包含所有reducer。
返回什么? 一个总的reducer。
JavaScript
export default function combineReducers(reducers) {
return function combination(state = {}, action) {
let nextState = {};
let hasChanged = false;
for (let key in reducers) {
const reducer = reducers[key];
nextState[key] = reducer(state[key], action);
hasChanged = hasChanged || nextState[key] !== state[key];
}
hasChanged =
hasChanged || Object.keys(reducers).length !== Object.keys(state).length;
return hasChanged ? nextState : state; //优化一下,判断一下当前状态值到底变了没有,不改变就返回老的。
};
}