这套封装写法和vuex中的写法一样。
- 1、下载redux、react-redux
"react-redux": "^7.2.8",
"redux": "4.1.2",
- 2、在src目录下创建store:/src/store,store目录下有两个文件:index.ts、reducer.ts
--src
--store
index.ts
reducer.ts
- 3、index.ts文件内容
import { createStore } from 'redux';
import reducer from './reducer.ts'
export default createStore(reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
- 4、reducer.ts文件内容
defaultState是初始化state存储内容
import handleNumber from './numberState/index.ts'
import handleString from './stringState/index.ts'
//每次导入每个模块,只需要在这里注册一遍名称就可以,下面会自动封装解构数据和action方法
let storeName = {
handleNumber,handleString
}
// 通过storeName自动结构其里面数据方法
function mergeModulesState(modules:any) {
let mergedState = {};
for (let moduleName in modules) {
if (modules.hasOwnProperty(moduleName) && modules[moduleName].state) {
mergedState = { ...mergedState, ...modules[moduleName].state };
}
}
return mergedState;
}
//解构初始化数据存储
const defaultState = mergeModulesState(storeName)
//解构action执行方法
let reducer = (state = defaultState, action: { type: string,val:number }) => {
let newState = JSON.parse(JSON.stringify(state))
console.log('aaa=', storeName);
for (let keyName in storeName) {
// @ts-ignore
for (let key in storeName[keyName].action) { //ts
if (action.type == key) {
// @ts-ignore
storeName[keyName].action[key](newState, action);
break;
}
}
}
return newState;
}
export default reducer;
- 5、在src目录下创建global.d.ts,配置全局的接口
声明在index.ts文件中window类型报错配置
/*
全局的ts类型声明文件
*/
// 配置redux开发者工具配置项接口类型
interface Window {
__REDUX_DEVTOOLS_EXTENSION__: function;
}
- 6、每个模块写法:/src/store/numberState/index.ts
这种写法就和vue中的vuex很相似了
export default {
state: {
num: 20
},
action: {
add(newState: any, action: any) {
newState.num++;
}
}
}
- 7、组件中使用
useSelector:获取store中的state数据
useDispatch:获取store中的dispath函数
import { useSelector, useDispatch } from "react-redux";
export default function Home() {
// const { num } = useSelector((state) => {
// return state;
// });
// 定义状态类型
interface AppState {
num: number;
}
const { num } = useSelector((state: AppState) => state);
const dispath = useDispatch();
const changeNum = () => {
dispath({
type: "add",
val: 2,
});
};
return (
<>
<div>Home:{num}</div>
<button onClick={changeNum}>点击</button>
</>
);
}
这样子每次创建不同模块都要遵循模块写法,并且还要在reducer.ts文件里面导入,把其名称注册到storeName中,就可以在全组件中使用了
注意点:这种创建方式存在模块之间命名冲突问题,需要注意一下,可以约束一下每个模块之间命名前缀