10 个步骤轻松掌握 ReduxToolkit

简介: 10 个步骤轻松掌握 ReduxToolkit

如果你在用 React,那你也应该使用 Redux。

如果你在用 Redux,那你也应该使用 RTK。

RTK 全拼 Redux-Toolkit,是 Redux 的官方工具包,致力于让 Redux 更易于使用。

这篇文章将分成 10 个步骤教你快速掌握 RTK。

在阅读之前,你最好知道一些 Redux 的知识。


1. 创建 store


使用 configureStore创建 store。

store 中保存所有的数据以及更新数据的操作(reducer)。

使用 Provide组件包裹你的所有组件。


import { configureStore } from "@reduxjs/toolkit"
import { Provider } from "react-redux"
// 也可以配置 middleware 和 enhancer
const store = configureStore({
  reducer: {
  // 改变数据的函数
  }
})
const Container = () => (
  // Provider 组件可以将 store 以上下文的方式注入到根组件中,这样所有的组件都可以使用上下文
  <Provider store={store}>
    <App />
  </Provider>
)


2. 创建命名切片(slice)


slice 包含一部分状态和可以更新这部分状态的函数。

我们通常以模块来划分 Slice,比如商城系统可以设计成 GoodcartSlice、ShopSlice、OrderSlice 等。

这样做的好处是将业务高内聚,不再为了修改一个 action 而去修改 N 个文件。


import { createSlice } from "@reduxjs/toolkit"
export const counterSlice = createSlice({
  name: 'counter',// 每个 slice 必须有一个名字,而且需要是唯一的。
  // 设置初始状态
  initialState: {
    count: 0
  },
  // reducers 可以自动创建 actions
  reducers: {
  }
})


3. 将 slice 中的 reducer 添加到 store 中


我们在 createSlice 中定义的 reducers(复数)会在 counterSlice 对象上自动创建 reducer(单数)属性。

将 slice.reducer 添加到 store 中。


const store = configureStore({
   reducer: {
     // reducer 的 key 需要和 slice 的 name 保持一致
     counter: counterSlice.reducer// reducer 会根据配置对象的 reducers 自动创建
   }
 })


4. 在 slice 的 reducers 中编写逻辑


reducer 可以获取当前的状态和正在执行的 action,并更新 Slice 中的 state。

RTK 内部自动使用 immer,所以这些 state 的变化都是不可变的。


import { createSlice } from "@reduxjs/toolkit"
export const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    count: 0
  },
  reducers: {
    // reducers 的每个方法都可以接收到当前的状态
    // 方法的第二个参数可以自动接收 actions,这个例子中没有用到
    up: state => {
      state.count += 1// 这种写法像是在直接改变原数据,但 RTK 会使用 immer 让它变成不可变的操作
    },
    down: state => {
      state.count -= 1
    }
  }
})


5. 使用 useSelector 从 store 中取值


useSelector 函数可以访问 store 中所有的数据,并且可以值返回当前组件所需要的数据。

它是一个 hook,我们可以在任意一个被 Provider 包裹的组件中调用它。


import { useSelector } from "react-redux"
cosnt App = () => {
  // state 参数是 store 的所有数据
  // state.counter 是我们的命名 slice
  // 最后在 slice 中获取需要的值
  const count = useSelector(state => state.counter.count)
  return (
    <div>
      Count: {count}
    </div>)
}


6. 更改 store 的数据时,从 slice 中导出 actions


slice 会根据 reducers 自动生成一个 actions 属性,它包含了一组方法,但是我们不能直接调用,为它们需要当前的 state 和参数。


cosnt App = () => {
  const actions = counterSlice.actions
  // 此时 actions 身上包含两个方法:actions.up 和 actions.down
}


7. 使用 dispatch 调用 actions


我们需要使用 useDispatch hook 来访问 dispatch 函数,然后使用这个函数来调用 actions。

actions 更新 state 后,所有使用 useSelector 访问数据的组件都会自动更新。


cosnt App = () => {
  const count = useSelector(state => state.counter.count)
  const actions = counterSlice.actions
  // dispatch 是个方法,它可以调用 action
  const dispatch = useDispatch()
  // actions.up 会创建一个 action 对象
  const constUp = () => dispatch(actions.up())
  const constDown = () => dispatch(actions.down())
  return (
    <div>
      Count: {count}
      <button onClick={countUp}>+</button>
      <button onClick={countDown}>-</button>
    </div>)
}


8. 为 action 添加参数


action 也可以附带参数,作为 reducer 的第二个参数传入。

传递的数据 RTK 会自动帮我们挂载到 action 的 payload 属性上。


import { createSlice } from "@reduxjs/toolkit"
export const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    count: 0
  },
  reducers: {
    up: (state, action) => {
      state.count += action.payload || 1
    },
    down: (state, action) => {
      state.count -= action.payload || 1
    }
  }
})

在组件中传递参数。


cosnt App = () => {
  const count = useSelector(state => state.counter.count)
  const actions = counterSlice.actions
  const dispatch = useDispatch()
  const constUp = () => dispatch(actions.up())
  const constDown = () => dispatch(actions.down())
  const plusFive = () => dispatch(actions.up(5))
  const minusFive = () => dispatch(actions.down(5))
  return (
    <div>
      Count: {count}
      <button onClick={countUp}>+</button>
      <button onClick={plusFive}>+ 5</button>
      <button onClick={countDown}>-</button>
      <button onClick={minusFive}>- 5</button>
    </div>)
}


9. 使用 redux-thunk 处理异步操作


因为异步操作非常常见,所以 RTK 内置了 redux-thunk。

处理异步的方式就是创建一个 thunk 函数,它返回一个异步函数,然后在 thunk 函数中使用 dispatch 调用 action。


//  返回的异步函数默认接受 dispatch 作为参数
const fetchLength = () => async dispatch => {
  // 模拟 ajax 获取数据
  const result = await fetch("http://localhost:3000/api/length")
  const text = await result.text()
  const actions = counterSlice.actions
  // 当数据准备完毕后,使用 dispatch 调用 action
  dispatch(actions.up(text.length))
}

在组件中进行异步操作。


cosnt App = () => {
  const count = useSelector(state => state.counter.count)
  const actions = counterSlice.actions
  const dispatch = useDispatch()
  const constUp = () => dispatch(actions.up())
  const constDown = () => dispatch(actions.down())
  const plusFive = () => dispatch(actions.up(5))
  const minusFive = () => dispatch(actions.down(5))
  // 将 thunk 函数像 action 一样传递给 dispatch
  const countAsync = () => dispatch(fetchLength())
  return (
    <div>
      Count: {count}
      <button onClick={countUp}>+</button>
      <button onClick={plusFive}>+ 5</button>
      <button onClick={countDown}>-</button>
      <button onClick={minusFive}>- 5</button>
      <button onClick={countAsync}> async fetch </button>
    </div>)
}


10. Context 可以替代 Redux 吗?


通过上面的学习 ,我们发现即使是一个很简单的计数器应用,也要写大量的代码和使用繁琐的 API。

既然 ReactRedux 是使用 React 的 Context 来实现的,那我们只使用 Context 会怎么样呢?

对于小型项目,我更倾向于使用 Context。

但是对于大型项目和多人团队协作来说,Redux 有它不可替代的一些优势:

  • 更清晰的代码组织结构。
  • 更易于测试。
  • 提供了功能强大的 devtools。
  • 强大的生态系统。



相关文章
|
人工智能 分布式计算 算法框架/工具
揭开阿里巴巴PAI的神秘面纱:引领人工智能计算的新篇章
揭开阿里巴巴PAI的神秘面纱:引领人工智能计算的新篇章 随着人工智能技术的飞速发展,越来越多的企业开始关注并投入到AI的研究和应用中。阿里巴巴作为全球领先的科技公司,也在AI领域做出了卓越的贡献。今天,就让我们一起来揭开阿里巴巴PAI的神秘面纱,了解这个强大的AI平台如何引领人工智能计算的新篇章。 PAI,全称阿里巴巴公共AI平台,是一个集数据准备、模型开发与训练、模型部署于一体的综合性AI平台。PAI的业务架构分为五层,从基础设施层到业务层,涵盖了AI计算的全过程。
1664 2
|
敏捷开发 设计模式 测试技术
TDD简介
TDD简介
307 0
Java实现多文件打包成压缩包下载
Java实现多文件打包成压缩包下载
954 0
|
10月前
|
存储 人工智能 测试技术
HarmonyOS Next~HarmonyOS应用测试全流程解析:从一级类目上架到二级类目专项测试
本文深入解析HarmonyOS应用测试全流程,涵盖从一级类目通用测试到二级类目专项测试的技术方案。针对兼容性、性能、安全测试及分布式能力验证等关键环节,提供详细实践指导与代码示例。同时,结合典型案例分析常见问题及优化策略,帮助开发者满足华为严苛的质量标准,顺利上架应用。文章强调测试在开发中的核心地位,助力打造高品质HarmonyOS应用。
507 2
|
12月前
|
弹性计算 人工智能 安全
企业级DeepSeek调用指南:通过私网连接(PrivateLink)实现DeepSeek R1模型的稳定接入
DeepSeek R1是一款开源免费的高性能生成式AI模型,其发布引发全球技术社区广泛关注。在多项基准测试中,DeepSeek R1展现出与GPT-3比肩的核心性能指标,吸引了众多开发者和企业用户进行技术验证与场景适配。阿里云百炼平台已提供DeepSeek模型的公网调用支持,但考虑到数据安全与合规性挑战,建议通过私网连接(PrivateLink)建立安全调用通道,确保端到端的数据传输安全,并满足金融、医疗等强监管行业的合规要求。私网连接方案具备构建私有网络环境、实现毫秒级延迟服务调用、满足行业监管合规要求等优势,为企业提供数据安全与业务发展的双重保障。
企业级DeepSeek调用指南:通过私网连接(PrivateLink)实现DeepSeek R1模型的稳定接入
|
人工智能 智能硬件
如何在一周内摸清一个行业:ChatGPT + 麦肯锡关键词分析法
如何在一周内摸清一个行业:ChatGPT + 麦肯锡关键词分析法
2730 0
如何在一周内摸清一个行业:ChatGPT + 麦肯锡关键词分析法
|
存储 NoSQL 算法
周四埋下的坑,周五来恶补!! Redisson 加锁、锁自动续期、解锁源码分析
周四埋下的坑,周五来恶补!! Redisson 加锁、锁自动续期、解锁源码分析
834 2
|
存储 分布式计算 数据处理
使用Python和Pandas处理大型数据集的高效策略
随着大数据时代的到来,处理大型数据集已成为数据分析师和数据科学家的日常任务。本文旨在探讨如何使用Python的Pandas库高效地处理大型数据集。不同于常规的数据处理教程,本文将重点介绍数据子集化、内存优化、并行处理和数据压缩等高级策略,帮助读者在资源受限的环境中快速且准确地分析大量数据。
|
存储 JSON C#
C# 通过阿里云接口实现人脸属性识别
C# 通过阿里云接口实现人脸属性识别
|
机器学习/深度学习 人工智能 自然语言处理
大模型开发:描述模型可解释性的重要性以及如何实现它。
模型可解释性在AI和机器学习中至关重要,尤其在金融风控等领域,它关乎信任、公平性和法规合规。通过建立信任、发现偏见、排查错误和满足法规要求,可解释性促进了模型的改进和社会接受度。研究者采用简单模型、局部和全局解释方法、模型可视化及原型/反例等策略提升模型透明度。这是一项结合算法、专业知识和伦理的跨学科挑战。
983 1