react-redux项目工程搭建,vuex写法,基于react+vite+ts

这套封装写法和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中,就可以在全组件中使用了

注意点:这种创建方式存在模块之间命名冲突问题,需要注意一下,可以约束一下每个模块之间命名前缀

你可能感兴趣的:(react.js,javascript,前端)