React+RTK+TS动态渲染菜单

权限

路由的接口类型为Array
菜单的接口类型为MenuProps[‘items’], 为antd中结构,官网有

1、创建切片

import {createSlice,PayloadAction,Dipatch} from 'RTK';
// 导入接口
// initialState的类型是自定义的接口 IAuthInitalState
// IAuthInitalState的成员menus的类型Menus['props']

import {IAuthInitalState} from '接口文件地址'
导入转化工具
import {transfromRightMenus} from '../utils'
const initialState:IAuthInitalState = {
    menus:[]
    routes:[]
  }
const authSlice = createSlice({
  name:'authNs'
  initialState,
  reducers:{
    getMenus(state:IAuthInitalState,{payload}:PayloadAction<any>[]){ 
      state.menus = payload
    }
  }
})
export const getMenusAync = (dipatch:Dipatch)=>{
  let ary = transfromRightMenus(result.data.data)
    dipatch(getMenus(ary))
}
export const {getMenus} = authSlice.actions
export default authSlice.reducer

2、在types文件下创建users接口

import {MenuProps} from 'antd'
export interface IAuthInitalState{
  menus:MenuProps['items']
}
// 定义规范权限数据对象的接口
export interface IrightData{
  _id:string,
  title:string,
  pid:string,
  path:string,
  icon:string,
  children?:IrightData[]
}
// 定义规范AntdMenu对象的接口
export interface IAntdMenuItem{
  label:string
  key:string
  icon:React.ReactNode,
  children?:Array<IAntdMenuItem>
}

3、仓库入口文件配置

import { configureStroe} from 'RTK'
import auth from 'auth'
const store = configureStroe({
        reducer:{
          auth
        },
        middleWare:()=>{}
})
export default store

4、项目入口文件

import store from ' 仓库入口文件地址'
const root = ReactDom.createRoot(document.querSelector('root'))
root.render(
  <BrowserRouter >
        <Provider store={store}>
          <App />
        </Provider> 
  </BrowserRouter>
)

5、创建NavigateMenu组件

import React,{useEffect} from 'react'
// 这里不要导入useDipatch
// import {useDipatch} from 'react-redux'

// 导入useAppDipatch,这样dispatch(getMenusAync)不会报类型限制错
import {useAppDipatch,useAppSelector} from './store/hooks'
// 导入reducer
import {getMenusAync} from 'reducer地址'
//导入antd
import {Menus} from 'antd'
export default function NavigateMenu(){
  const dispatch = useAppDipatch()
  useEffect(()=>{
    dispatch(getMenusAync)
  })
  const items = useAppSelector((state)=>{
    return state.auth.menus
  })
}

6、 在store的创建hooks.tsx文件

import { useDispatch, useSelector } from 'react-redux'
import type { TypedUseSelectorHook } from 'react-redux'
import type { RootState, AppDispatch } from './index'

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

7、菜单转化,创建authUtils工具文件

1. 导入菜单接口限制
import {IRightData,IAntdMenuItem} from '@/接口地址'
2. 引入antd图标库
import * as icons from '@antd-deign/icons'
2. 将权限数据转成AuthMenu结构数据
export const transfromRightMenus = (list:Array<IRightData>)=>{
  return list.map(item=>{  
      let menuItem:IAntdMenuItem
      // 3.判断icon图标
      if(item.icon){
        // keyof的作用是将一个对象中的key联合起来作为一个新类型
        const iis:any = icons[item.icon as keyof typeof icons]
        menuItem={
          label:item.title,
          key:item.path,
          icon:React.createElement(iis)
        }
      }else{
        menuItem ={
          laebl:item.titile,
          key:item.path
        }
      }
      if(item.children&&item.children.length){
          menuItem.children = transfromRightMenus(item.children)
      }
      return menuItme
  })
}

8、在sotre中auth中配置

配置中间件serializableCheck,消除序列化报错

const store = configureStore({
    reducer:{
        authReducer
    },
    middleware:(getDefaultMiddleware)=>getDefaultMiddleware({serializableCheck:false})
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值