redux 详解(带你学习store、action、redux)

前言

react 用了一年多,但一直对 redux 了解不多,一直想找个机会彻底掌握它,所以有了今天这篇文章,如果你也对 redux 不够了解,那么可以仔细阅读下,相信会有所收获。

初识 redux

首先让我们清晰下 什么是redux?它有什么作用?

  • redux 是一个独立的、专门用于状态管理的JS库
  • 可以搭配 react、angular、vue 使用,不过主要用于搭配 react
  • 作用:集中管理 react 应用中多个组件共享的状态。

redux 原理

在这里插入图片描述

用文字来描述:

redux 将整个应用的 state 储存在 store 中,视图组件在 redux 中派发 action 方法,

action 通过 store 的 dispatch 方法派发给 store

store 接收 action,和之前的 state,一起传递给 reducer

reducer 实现更新 state 的动作后,返回新的 state 给 store,然后 store 去改变自己的 state 。

视图组件连接了 store,store 中的 state 更新后,视图组件的数据也就随之改变,从而重新渲染页面

三大原则(重点)

1. 单一数据源

整个应用的 state 被储存在一个 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。

简单点来说就是:

一个应用只能有一个 store 。

当我们的项目越来越复杂时,我们需要拆分数据处理逻辑,可以使用reducer组合,而不是创建多个store 对象

2. State 是只读的

唯一改变 state 的方法是 触发(dispatch) action,action 是一个对象,描述发生了什么事情,比如点击了按钮之类的操作。

3. 使用纯函数(reducer)执行修改

为了描述 action 如何改变 state 树,我们需要编写 reducers

接下来,我们来来了解怎么创建 store,及其对应的 API,什么是 reducer

store

store 是 redux 的核心,负责整合 action 和 reducer。

redux 提供了 createStore() 方法来创建一个store

import { createStore } from 'redux'
import reducer from './xxx.ts'

const store = createStore(reducer) // createrStore 接收一个 reducer 为参数

createStore 接收一个 reducer 为参数,它其实还有第二个参数,是可选的,用于设置 state 的初始状态

关于 store,我们常使用的 API 有三个:dispatchsubscribegetState

dispatch:用于更新state。

      用法:store.dispatch(action)

      注意:action 必须是一个对象,且 action.type 不能省略。

getState:用于获取 state

       getState 方法比较简单,就是获取 state,不过在返回 state 之前,会进行 isDispatching 判断,如果 isDispatching 为 true,则表示是在进行 reducer 阶段,等返回最新的 state 之后,将 isDispatching 赋值为 false。

       在 reducer 进行中,不能通过使用 store.getState() 来获取 state,因为我们已经通过 (state, action) => {} 传入了 state,不用在通过 getState 方法来获取。如果在 reducer 中使用了 getState,将会抛出一个错误提示。

subscribe:用来监听 state 的变化

       一旦 state 发生变化,就会自动执行这个函数。 其实是每次 dispatch 后,紧跟着都会执行我们之前通过 subscribe 注册的监听事件,我们可以在 listener 函数中通过 store.getState 获取最新的 state 状态树。

       subscribe 会返回一个函数,调用这个函数就可以解除监听。

useEffect(() => {
	// 监听 state 的变化
	let unSubscribe = store.subscribe(() => {
		console.log('我正在监听', store.getState())
	})
	return () => {
		// 取消监听
		unSubscribe()
	}
}, [])

action

首先,我们先解释下 action。

action 是把数据从应用传到 store 的有效载荷,它是 store 数据的 唯一来源。

我们通过 store.dispatch() 将action 传到 store。

action 本质上是一个 JavaScript 普通对象,描述已发生的事件,作用是告知 reducer 该更新 store 中哪些 state

action 内必须使用一个字符串类型type 字段来表示将要执行的动作

大部分情况下,type 会被定义为 字符串常量,通常是大写。

{
	type: 'ADD',
	payload: '测试'
}

{
	type: 'ADD',
	payload: {
		text: 'do something'
	}
}

{
	type: 'ADD',
	payload: new Error(),
	errro: true
}

除了 type 字段外,action 对象的结构完全有我们自己决定。

reducer 里通过收到的 action 的不同 type 值,去执行不同的修改 state 的行为。

通常来说,同步action 设置 type 就够了。异步action 除了必须的 type 属性外,我们还可以添加 payload、error、meta 等属性。

当系统中的action 越来越多时,建议把 action 单独抽出成一个文件。

如下面代码实例所示:

store/action/config.js

export const INCREMENT = 'INCREMENT',
export const DECREMENT = 'DECREMENT'

store/action/index.js

import * as constant from './config'

export const incrementNum = () => ({
	type: constant.INCREMENT,
})

export const decrementNum = () => ({
	type: constant.DECREMENT,
})
// 优化之前
addNum = () => {
	store.dispatch({type: 'INCREMENT'})
}
decreNum = () => {
	store.dispatch({type: 'DECREMENT'})
}

// 优化之后

addNum = () => {
	store.dispatch(actions.incrementNum())
}
decreNum = () => {
	store.dispatch(actions.decrementNum())
}

reducer

当 dispatch 发起了一个 action 后,会来到 reducer

reducer 就是用来计算新的 store 的,描述action 如何改变 state 树。

reducer 是一个纯函数,接收两个参数,参数为 当前state 和 action,返回一个新的 state。

store 在收到 action 之后,传递给 reducer,reducer 计算出新的 state 后返回,view 才会发生变化。这种state 的计算过程就叫做 reducer。

注意:在首次使用 redux时,我们需要给 state 一个默认值

// 这就是一个 reducer, 这个是 state 是基本类型
const counter = (state = 0, action) => {
	switch(action.type) {
		case 'INCREMENT':
			return state + 1
		case 'DECREMENT':
			return state - 1
		default:
			return state
	}
}

// 当 state 为引用类型时
const initState = {
	number: 0
}
const counter = (state: initValue, action) => {
	switch(action.type) {
		case 'INCREMENT':
			return {
				...state,
				number: state + 1
			}
		case 'DECREMENT':
			return {
				...state,
				number: state - 1
			}
		default:
			return state
	}
}

let store = createStore(counter)

combineReducers

随着应用变的越来越复杂,我们可以考虑将 reducer 函数拆分成多个单独的函数,拆分后的每个函数负责独立管理 state 的一部分,此时我们就需要用到 combineReducers。

combineReducers 辅助函数的作用是:把一个由多个不同的 reducer 函数作为 value 的 object,合成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore 方法。

举一个比较好的例子

reducers.js

// reducers.js

export default theDefaultReducer = (state = 0, action) => {
	switch(action.type) {
		case 'ADD':
			return state + 1
		case 'DEC': 
			return state - 1
		default:
			return state
	}
}

export firstReducer = (state = 1, action) => {
	switch(action.type) {
		case 'ADD':
			return state + 1
		case 'DEC': 
			return state - 1
		default:
			return state
	}
}

export secondReducer = (state = 2, action) => {
	switch(action.type) {
		case 'ADD':
			return state + 1
		case 'DEC': 
			return state - 1
		default:
			return state
	}
}

rootReducer.js

// 根reducer 
import { combineReducers, createStore } from 'redux';

import theDefaultReducer, { firstReducer, secondReducer } from './reducers'

// 使用了 ES6 的对象字面量简写方式定义对象结构
const rootReducer = combineReducers({
	theDefaultReducer,
	firstReducer,
	secondReducer
})

const store = createStore(rootReducer);
console.log(store.getState())
// { theDefaultReducer: 0, firstReducer: 1, secondReducer: 2 }

看到这里,相信你会对 redux 有一个初步的认知,不会在向以前一样摸不到头脑。

不过 redux 的知识可不止这一些,还有很多用法在这里没有说到,之后有机会我再往上补充吧,或者去学习官网,官网才是最权威的地方。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值