返回顶部

umijs+react+dva——状态管理,实现非兄弟、父子组件传值以及回调

参考:

1.Umi】umi-max 中使用 Dva https://juejin.cn/post/7373606026027237413

 

我的项目是:umijs+react

 效果:

 

1.安装dva

npm install dva

 Dva 是一个基于 Redux、Redux-Saga 和 React-Router 的数据流管理框架。

 

2.umirc.ts文件中配置dva

export default defineConfig({
  dva: {},
  // 其他配置
})

 

3.创建 Model,在 Umi 项目的 src/models 目录下创建一个新的文件,例如 test-switch.ts,用于定义一个模型。test-switch.ts:

import { updateSwitchRequest } from '../api' // 自己封装的请求

export default {
  namespace: 'testSwitch', // model 的命名空间,唯一标识符,对应 redux 中的 state key
  state: {
    switchVal: true, // 初始状态
  },
  // reducers 中处理同步逻辑,更新 state
  reducers: {
    onChangeSwitch(state: any, { payload: switchVal }) {
      return {
        ...state,
        switchVal,
      }
    },
  },
  // 异步更新仓库状态数据
  effects: {
    *fetchData({ payload }, { call, put }) {
      try {
        const response = yield call(updateSwitchRequest, payload) // 调用异步请求接口
        yield put({ type: 'onChangeSwitch', payload: response.data }) // 触发对应的 reducer
      } catch (err) {
        console.log('err', err)
      }
    },
  },
}

 

4.开关组件,SwitchComponent.tsx:

import { connect } from '@umijs/max'
import { useRequest } from '@umijs/max'
import { useDispatch } from '@umijs/max'
import { Switch } from 'antd'
import { useEffect, useState } from 'react'
import { querySwitchRequest } from '../api' // 自己封装的请求

export function mapStateToProps(state: any) {
  const { switchVal } = state.testSwitch // testSwitch就是models命名空间名字
  return {
    switchVal, // 在这return,才能获取到
  }
}

function SwitchComponent(props: any) {
  const dispatch = useDispatch()
  const [val, setVal] = useState<boolean>(false)
  const { data } = useRequest(() => querySwitchRequest ())

  dispatch({ type: 'testSwitch/onChangeSwitch', payload: data })

  useEffect(() => {
    if (props) {
      setVal(props.switchVal)
    }
  }, [props])

  return (
    <>
      <div>
        开关组件
        <Switch
          value={val}
          onChange={v => {
            dispatch({ type: 'testSwitch/fetchData', payload: { enable: v } })
          }}/>
      </div>
    </>
  )
}

export default connect(mapStateToProps)(SwitchComponent)

 

5.页面中使用,父组件Parent.tsx: 

import type { TabsProps } from 'antd'
import { Card, Tabs } from 'antd'
import { useCallback } from 'react'
import { useLocation, history, Outlet } from '@umijs/max'
import SwitchComponent from '../components/switch-component'

const items: TabsProps['items'] = [
  {
    key: '/parent/child1',
    label: '子组件1',
  },
  {
    key: '/parent/child2',
    label: '子组件2',
  },
]

export default function ParentPage() {
  const { pathname } = useLocation()
  const handleChange = useCallback((key: string) => {
    history.push(key)
  }, [])

  return (
    <>
      <Card title='父组件'>
        <SwitchComponent />
        <Tabs defaultActiveKey={pathname} items={items} onChange={handleChange} />
        <Outlet />
      </Card>
    </>
  )
}

6.子组件Child1.tsx:

import { connect } from '@umijs/max'
import { mapStateToProps } from '../../components/switch-component'

function WindowsPage(props: any) {
  return <div>开关状态:{props.switchVal ? '开启' : '关闭'}</div>
}

export default connect(mapStateToProps)(WindowsPage)

7.route和目录层级:

{
    name: '父菜单',
    path: '/parent',
    routes: [
      {
        path: '/parent',
        redirect: '/parent/child1',
      },
      {
        name: '子菜单1',
        path: '/parent/child1',
        component: '@/pages/parent/child1',
      },
      {
        name: '子菜单2',
        path: '/parent/child2',
        component: '@/pages/parent/child2',
      },
    ],
  },

 

posted @ 2025-05-13 09:55  前端-xyq  阅读(220)  评论(0)    收藏  举报