携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
前言
大家好呀,我是L同学。在上篇文章react笔记(十二)—— 自定义hooks中,我们学习了自定义hooks、使用useEffect发送请求、使用useRef操作DOM、useContext等相关知识点。在本篇文章中,我们将学习到redux基本介绍、redux 开发环境准备、Redux 三个核心概念(action/reducer/store)等相关知识点。
redux介绍
redux 是 react 中最流行的状态管理工具之一 。React 只是 DOM 的一个抽象层(UI 库),并不是 Web 应用的完整解决方案。因此react在涉及到数据的处理以及组件之间的通信时会比较复杂。为什么要使用redux呢?主要的区别是组件之间的通讯问题。
不使用 Redux:
- 只能使用父子组件通讯、状态提升等 React 自带机制
- 处理远房亲戚(非父子)关系的组件通讯时乏力
- 组件之间的数据流混乱,出现 Bug 时难定位
使用 Redux:
- 集中式存储和管理应用的状态
- 处理组件通讯问题时,无视组件之间的层级关系
- 简化大型复杂应用中组件之间的通讯问题
- 数据流清晰,易于定位 Bug
redux 开发环境准备
使用 React CLI 来创建项目,并安装 Redux 包即可:
- 创建 React 项目:
npx create-react-app redux-basic - 启动项目:
yarn start - 安装 Redux 包:
yarn add redux
Redux 核心概念
为了让代码各部分职责清晰、明确,Redux 代码被分为三个核心概念:action/reducer/store。
- action(动作):描述要做的事情
- reducer(函数):更新状态
- store(仓库):整合 action 和 reducer
Redux核心概念-action
action描述要做的事情,项目中的每一个功能都是一个 action。比如,计数器案例中的计数器加1、减1,todomvc 案例中的添加任务、删除任务等,项目中的登录,退出等。
action只描述做什么。它是一个JS 对象,必须带有 type 属性,用于区分动作的类型。根据功能的不同,可以携带额外的数据(payload),配合该数据来完成相应功能。
// action
{ type: 'increment' }
{ type: 'decrement', payload: 2 }
// todomvc 案例
// { type: 'addTodo' }
{ type: 'addTodo', payload: '吃饭' }
{ type: 'addTodo', payload: '睡觉' }
// { type: 'removeTodo' }
{ type: 'removeTodo', payload: 3 }
Redux核心概念-action creator
直接使用对象来创建action不灵活,参数写死了。一般会使用函数来创建action,我们把创建action的函数叫做actionCreator。action creator创建函数只是简单的返回一个 action。action creator创建函数的好处是更容易被移植和测试。
const increment = {
type: 'INCREMENT'
}
const increment = () => {
return {
type: 'INCREMENT'
}
}
const increment = () => ({
type: 'INCREMENT'
})
// 使用action创建函数:(添加任务)
const addTodo = {
type: 'ADD_TODO',
text: '加班'
}
const addTodo = (text) => ({
type: 'ADD_TODO',
text
})
addTodo('加班') // {type: '', text: ''}
addTodo('下课')
Redux核心概念-reducer
reducer这个名字是参考了 JS 数组中的 reduce 这个方法。数组中的reduce方法,可以来实现累积,比如,累加或者累减。reducer是一个函数,用来处理action,更新状态,是 Redux 状态更新的地方。reducer函数接收上一次的状态和 action 作为参数,根据 action 的类型,执行不同操作,最终返回新的状。reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。原则是不要在reducer函数内部直接修改state。
export default function reducer(state = 100, action) {
// 处理各种各样的action
switch (action.type) {
case 'addOne':
return state + 1
case 'subOne':
return state - 1
case 'addMore':
return state + action.payload
case 'subMore':
return state - action.payload
default:
// 很重要
return state
}
}