Redux 及Redux-Toolkit 使用笔记及简易实现
依赖的包 npm install @reduxjs/toolkit react-redux
创建Store并且将它注入到app中。
- 一般使用
configureStore({reducers:{}})
,这种方式,我们可以在各个模块里面定义各自的reducer,然后在store里面使用它。这个方法返回的就是store的实例,它里面有store:{dispatch:Function,getState:Function}
等方法,整个app对于store的API调用,都得靠这个对象。 - 我们也可以在hook函数中来使用store,在App的顶层,我们使用
import {Provider} from 'react-redux';<Provider store={storeinstance}></Provider>
.这样我们就可以在全局使用useSelector(selector:Func,options?:EqualFunc)
的方式来对于store进行引用。 - 我们也可以将store里面的slice 通过组件的参数来传递到组件。可以使用
function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)
,用法其实是一种HOC的写法,export MyComponnet = connect()(InnerComponent)
。
Store可以看成是整个数据库,里面得需要各自不同的表,所以,我们有了Slice的概念。
- toolkit里面提供了
const slice = createSlice(opts:{name:string,initializeValue:any,reducers:{}})
。先来看看它返回的slice
对象.最重要的两个是reducer,actions
.其中reducer我们得把它交给configureStore,而它的actions,我们可以结合dispatch来使用dispatch(someAction(payload))
。
export interface Slice<State = any, CaseReducers extends SliceCaseReducers<State> = SliceCaseReducers<State>, Name extends string = string> {
/**
* The slice name.
*/
name: Name;
/**
* The slice's reducer.
*/
reducer: Reducer<State>;
/**
* Action creators for the types of actions that are handled by the slice
* reducer.
*/
actions: CaseReducerActions<CaseReducers>;
/**
* The individual case reducer functions that were passed in the `reducers` parameter.
* This enables reuse and testing if they were defined inline when calling `createSlice`.
*/
caseReducers: SliceDefinedCaseReducers<CaseReducers>;
/**
* Provides access to the initial state value given to the slice.
* If a lazy state initializer was provided, it will be called and a fresh value returned.
*/
getInitialState: () => State;
}
- 那如何读取slice里面的数据,我们可以通过
const readSlice = createSelector(sliceselector1,sliceSelector2,...,joinResultFunc)
,这个API或者通过useSelector(sliceSelector)
。这两种有什么区别createSelector
是API调用,所以不要放到FC里面,它其实是提高了一个缓存的方式。如果所以的依赖项返回的值的引用都没有变化,那么readSlice(state)
,其实是不会执行的,返回的值还是上次的值,跟React.memo()
有点类似。useSelector()
这个是hook函数,当state里面的状态变化了,这个hook一定会被执行,如果返回的值发生了变化,那么,组件会刷新。所以,如果将createSelector
返回的值,传递给useSelector,那么就起到了一个缓存的作用。如果State
发生变化,但是我们关注的slice没有发生变化,那当前组件是不会刷新的。还要注意的是每次组件render的时候,useSelector()
里面的函数都会执行,如果返回的值没有变化,则返回值不变。所以使用createSelect的返回值,起到了一种优化的作用。
- 还要一个关键,
createSlice
里面的reducers应该怎么写?
它其实就是一个{[key:string]:(previousState,action)=>newState|void}
。这个createSlice
内部使用了immerjs来帮助我们做优化,所以,如果我们之间对原始的对象做了修改,它内部会将它转变成新的对象。
最后一个问题能否实现一个简单的实现
createSlice
的简易实现
function createSlice(opts:{name:string,reducer:{[k in string]:(previous:any,action:{type:string})=>any},initialValue}){
const {name,reducer,initialValue}=opts;
const [actions,reducers]=[{},{}];
let result={name,initialValue,actions,reducers};
const getSliceData=(state)=>state[name];
for(let [actionName,reduceFunc] of Object.entries(reducer)){
const actionFunc=(payload:any)=>{
return {
type:`${name}-${actionName}`,
payload,
}
};
const reducer=(previous:any,action:{type:string,payload:any})=>{
return reduceFunc(getSliceData(previous),action);
}
Object.assign(actions,{[actionName]:actionFunc});
Object.assign(reducers,{[actionName]:reducer})
}
return result;
}
useSelector(selectFunc)
的简易实现
function useSelector(selectFunc){
const store = useStore();
const sliceData= React.useMemo(()=>{
return selectFunc(store)
},[store]);
return sliceData;
}
createSelector(...dependencies,joint)
的简易实现
function createSelector(selectFunc){
const dependencies=arguments||[].slice(0,arguments.length-1);
const joint=arguments[arguments.length-1]
return function(state,...remainging){
const dependencyValues = dependencies.map(it=>it(state,...remainging));
return React.useMemo(()=>{
return joint(dependencyValues,...remainging);
},dependencyValues)
}
}
ConfigureStore(opts)
的简单实现
function configStore(opts:{reducers,}){
const {reducers}=opts;
let _innerDipatch:Function|null;
let _state:any;
const dispatch=(action)=>{
_innerDipatch(action);
}
const getState=()=>{
return _state;
}
const setDispatch=(dispatchFunc)=>{
_innerDipatch=dispatchFunc;
};
const updateStore=(state)=>{
_state=state;
}
const reducersWrapper=(previousState,action)=>{
const {type,payload}=action;
return reducers[type](previousState,payload);
}
return {dispatch,getState,reducersWrapper,setDispatch,updateStore}
}
const ReduxContext=React.createContext({store:{},dispatch:()=>{}});
function useStore(){
return React.useContext(ReduxContext).store;
}
function useDipatch(){
return React.useContext(ReduxContext).dispatch;
}
function ReduxProvider(props:{store:any,children:any}){
const {store}=props;
const [state,dispatch]=React.useReducer(store.reducersWrapper,{});
React.useEffect(()=>{
store.setDispatch(dispatch);
store.updateStore(state);
},[store,state]);
return (
<ReduxContext.Provider value={{state,dispatch}}>
{children}
</ReduxContext.Provider>
)
}
标签:const,reducer,Toolkit,笔记,state,return,Redux,store,reducers
From: https://www.cnblogs.com/kongshu-612/p/18345550