10分钟快速上手Redux-toolkit

@reduxjs/toolkit

这是React官网推荐的Redux公共状态管理工具

官网地址: cn.redux.js.org/introductio...

Demo GIt: gitee.com/tcwty123/re... 分支: @reduxjs/toolkit

相比于最原始的Redux,redux toolkit最大的特点是:

基于切片机制,把reducer和actionCreator混合在一起了,并且内部集成了immer 不需要克隆一份state

1. 下载

js 复制代码
yarn add react-redux
yarn add yarn add @reduxjs/toolkit

2. 目录结构

3. 文件编写内容

Index.js

js 复制代码
import { configureStore } from '@reduxjs/toolkit'

// 中间件
// import reduxLogger from 'redux-logger'
import reduxThunk from 'redux-thunk'

// 切片模块
import taskReducer from '../store/features/taskSlice'
// 切片原理
const store = configureStore({
  // 指定 reducer
  reducer: {
    // 按模块管理各个切片导出的reducer
    task: taskReducer,
  },
  // 使用中间件[如果我们不指定任何中间件,则默认集成了ReduxThunk,但是一旦设置,会整体替换默认值,需要手动指定thunk中间件]
  middleware: [reduxThunk],
})

export default store

切片文件=>taskReducer

js 复制代码
import { createSlice } from '@reduxjs/toolkit'

const taskSlice = createSlice({
  // 设置切片的名字
  name: 'task',
  // 设置次切片对应reducer中的初始状态
  initialState: {
    taskList: [],
    count: 0,
  },
  // 编写业务代码处
  reducers: {
    setCount(state, action) {
      // state:redux中公共状态信息.基于immer库,不需要自己克隆
      // action: 派发的行为对象,我们无需考虑行为标识,传递的其他信息,都是以action.payload的方式传递进来的值
      state.count = action.payload
    },
    setTaskList(state, action) {
      state.taskList = action.payload
    },
  },
})

// 利用promise 写一个异步的函数方法,返回一个数组
export function getTaskList() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve([1, 2, 3])
    }, 1000)
  })
}

// 从切片中获取actionCreator:此处结构的方法和上线reducers中的方法,仅仅是函数名相同;执行方法,返回需要派发的行为对象,后期我们可以基于dispatch进行任务派发即可!!
export let { setCount, setTaskList } = taskSlice.actions
console.log(setCount([])) // {"type": "task/setCount", "payload": []}

// 实现异步派发[redux-thunk]
export const getTaskListAsync = () => {
  return async (dispatch) => {
    let res = await getTaskList()
    // 注意派发时,需要使用 setTaskList
    dispatch(setTaskList(res))
  }
}

export default taskSlice.reducer

4. 入口注册store

main.js

js 复制代码
// 导入store
import store from './store'
import { Provider } from 'react-redux'
import Demo from './views/Demo'

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <Demo />
    </Provider>
  </React.StrictMode>
)

5. 获取redux公共状态和派发的方法

获取公共状态 useSelector

其中 taskList, count 就是在task切片中定义的状态

js 复制代码
const { taskList, count } = useSelector((state) => state.task)

获取派发的事件 useDispatch

js 复制代码
const dispatch = useDispatch()
dispatch(setTaskList(res)) dispatch中的内容相当于 action.payload

6. extraReducers 用于处理其他切片中的action

使用场景:一个事件中,需要修改两处切片中的值,可以通过例如Aaction让A以及B进行状态的修改

例如登出功能

AutoSlice.js

这里需要删除name字段

js 复制代码
import { createSlice } from '@reduxjs/toolkit'

const logoSlice = createSlice({
  name: 'logo',
  initialState: {
    name: 'logo',
  },
  reducers: {
    delName(state, action) {
      state.name = ''
    },
  },
})

export default logoSlice.reducer
export const { delName } = logoSlice.actions

TaskSlice.js

这里需要删除userInfo字段

js 复制代码
import { delName } from './AuthSlice'
// extraReducers 用于处理其他切片中的action
  extraReducers: (builder) => {
    builder.addCase(delName, (state, action) => {
      state.userInfo = {}
 })

此时在组件中调用delName的派发事件

即可删除name 以及userInfo

js 复制代码
import { delName } from '../store/features/AuthSlice' 
const handleLogoOut = () => {
    dispatch(delName())
 }

7. 完整demo案例

  1. store/index
js 复制代码
import { configureStore } from '@reduxjs/toolkit'

// 中间
// import reduxLogger from 'redux-logger'
import reduxThunk from 'redux-thunk'

// 切片模块
import taskReducer from '../store/features/taskSlice'
import logoReducer from '../store/features/AuthSlice'
// 切片原理
const store = configureStore({
  // 指定 reducer
  reducer: {
    // 按模块管理各个切片导出的reducer
    task: taskReducer,
    logo: logoReducer,
  },
  // 使用中间件[如果我们不指定任何中间件,则默认集成了ReduxThunk,但是一旦设置,会整体替换默认值,需要手动指定thunk中间件]
  middleware: [reduxThunk],
})

export default store
  1. features/AuthSlice
js 复制代码
import { createSlice } from '@reduxjs/toolkit'

const logoSlice = createSlice({
  name: 'logo',
  initialState: {
    name: 'logo',
  },
  reducers: {
    delName(state, action) {
      state.name = ''
    },
  },
})

export default logoSlice.reducer
export const { delName } = logoSlice.actions
  1. taskSlice
js 复制代码
import { createSlice } from '@reduxjs/toolkit'
import { delName } from './AuthSlice'

const taskSlice = createSlice({
  // 设置切片的名字
  name: 'task',
  // 设置次切片对应reducer中的初始状态
  initialState: {
    taskList: [],
    count: 0,
    userInfo: {
      name: 'zs',
      age: 20,
    },
  },
  // 编写业务
  reducers: {
    setCount(state, action) {
      console.log(action)
      // state:redux中公共状态信息.基于immer库,不需要自己克隆
      // action: 派发的行为对象,我们无需考虑行为标识,传递的其他信息,都是以action.payload的方式传递进来的值
      state.count = action.payload
    },
    setTaskList(state, action) {
      state.taskList = action.payload
    },
    setUserInfo(state, action) {
      state.userInfo = action.payload
    },
  },
  // extraReducers 用于处理其他切片中的action
  extraReducers: (builder) => {
    builder.addCase(delName, (state, action) => {
      state.userInfo = {}
    })
  },
})

// 利用promise 写一个异步的函数方法,返回一个数组
export function getTaskList() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve([1, 2, 3])
    }, 1000)
  })
}

// 从切片中获取actionCreator:此处结构的方法和上线reducers中的方法,仅仅是函数名相同;执行方法,返回需要派发的行为对象,后期我们可以基于dispatch进行任务派发即可!!
export let { setCount, setTaskList } = taskSlice.actions
console.log(setCount([])) // {"type": "task/setCount", "payload": []}

// 实现异步派发[redux-thunk]
export const getTaskListAsync = () => {
  return async (dispatch) => {
    let res = await getTaskList()
    // 注意派发时,需要使用 setTaskList
    dispatch(setTaskList(res))
  }
}

export default taskSlice.reducer
  1. 项目入口
js 复制代码
// 导入store
import store from './store'
import { Provider } from 'react-redux'
import Demo from './views/Demo'

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <Demo />
    </Provider>
  </React.StrictMode>
)
  1. 在某个组件中使用
js 复制代码
import { useDispatch, useSelector } from 'react-redux'
import {
  setCount,
  getTaskListAsync,
  getTaskList,
  setTaskList,
} from '../store/features/taskSlice'
import { useEffect } from 'react'
import { delName } from '../store/features/AuthSlice'

const Demo = () => {
  /* 获取redux公共状态和派发的方法 */
  const { taskList, count, userInfo } = useSelector((state) => state.task)
  const { name } = useSelector((state) => state.logo)
  const dispatch = useDispatch()

  const getData = async () => {
    const res = await getTaskList()
    dispatch(setTaskList(res))
  }
  useEffect(() => {
    // dispatch(getTaskListAsync())
    getData()
  }, [])

  const handleClick = () => {
    dispatch(setCount(count + 1))
  }
  const handleLogoOut = () => {
    dispatch(delName())
  }
  return (
    <div>
      123 - {count} - {JSON.stringify(taskList)} - {JSON.stringify(userInfo)} -{' '}
      {name}
      <br />
      <button onClick={handleClick}>add</button>
      <br />
      <button onClick={handleLogoOut}>logoOut</button>
    </div>
  )
}

export default Demo
相关推荐
小二·19 分钟前
Python Web 开发进阶实战(终章):从单体应用到 AI 原生生态 —— 45 篇技术演进全景与未来开发者生存指南
前端·人工智能·python
m0_6372565843 分钟前
vue-baidu-map添加了类型组件导致非常卡顿的问题
前端·javascript·vue.js
挂机且五杀1 小时前
为什么在React地图组件里,memo 不是优化,而是生存?
前端·react.js·前端框架
RFCEO1 小时前
HTML编程 课程七、:HTML5 新增表单标签与属性
前端·html·html5·搜索框·手机号·邮箱验证·日期选择
刘一说1 小时前
Vue开发中的“v-model陷阱”:为什么它不能用于非表单元素?
前端·javascript·vue.js
利刃大大2 小时前
【Vue】组件生命周期 && 组件生命周期钩子
前端·javascript·vue.js·前端框架
Easonmax2 小时前
基础入门 React Native 鸿蒙跨平台开发:实现面包屑导航
react native·react.js·harmonyos
Easonmax2 小时前
基础入门 React Native 鸿蒙跨平台开发:冒泡排序动画可视化
react native·react.js·harmonyos
建群新人小猿3 小时前
陀螺匠企业助手—个人简历
android·大数据·开发语言·前端·数据库
CHU7290353 小时前
在线教学课堂APP前端功能:搭建高效线上教学生态
前端·人工智能·小程序·php