react的状态管理库

1.Redux

本文引用了,这篇掘金文章,这篇文章写的挺好的,b站也有她的视频!
redux

1)redux的官方介绍

redux的官方描述:项目中所有的state都以一个对象树的形式存储在一个单一的store中。唯一改变state的办法是触发action,一个描述发生什么的对象。为了描述action如何改变state树,则需要编写reducers
redux的官方例子:

import { createStore } from "redux";
//这是一个reducer,形式(state,action) => state 的纯函数
//描述了action如何把state转变为下一个state

//state的形式取决于你,可以是基本类型,数组或者对象
//甚至是Immutable.js生成的数据结构。唯一的要点是
//当state变化时需要返回全新的对象,而不是修改传入的参数

//下面例子使用'switch'语句和字符串来做判断,但是你可以写帮助类(helper)
//根据不同的约定来判断,只要适合你的项目即可
function counter(state = 0, action){
	switch(action.type){
		case 'INCREMENT':
			return state + 1;
		case 'DECREMENT':
			return state -1;
		default:
			return state;
	}
}

//创建Redux Store来存放项目状态
//API 是{ subscrible, dispatch, getState }
let store = createStore(counter);

//可以手动订阅更新,也可以事件绑定到视图层
store.subscrible(()=>
	console.log(store.getState())
)

//改变内部state唯一方法是dispatch一个action
//action可以被序列化,用日记记录和存储下来,后期还可以以回放的方式执行
store.dispatch({type: 'INCREMENT'});
store.dispatch({type: 'INCREMENT'});
store.dispathc({type: 'DECREMENT'}):

要做的修改变成一个普通对象,这个对象被叫做action,而不是直接修改state。然后编写专门的函数来决定每个action如何改变项目中的state,这个函数被叫做reducer

2)副作用

副作用让函数变得不纯。如果依赖于外部状态就无法保证输出相同,就会带来副作用。
所有的外部交互都有可能产生副作用,副作用会给程序带来安全隐患和不确定性,要尽可能的控制副作用在可控制的范围内发生。

3)纯函数

纯函数要满足三个特点:(1)相同的输入总是会返回相同的输出 (2)不产生副作用 (3)不依赖于外部状态

var a = 10
function f(b){
	return a+b
}
console.log(f(5))
//因为全局a=10时,输出是15,当全局的a=0时,输出是5。
//所以上面的函数不满足上面的第一条和第三条规定,不是纯函数。
obj = {}
function f(b){
	obj.a = 10
	return b
}
console.log(f(5))
//因为函数改变了全局作用域里面的obj。
//所以不满足第二条规定,该函数不是纯函数。

4)redux的三大核心

  1. 单一数据源
    整个项目的state被存储在一棵object tree中,并且这个object tree只存在于唯一一个store中。
  2. State是只读的
    唯一改变state的方法就是触发actionaction是一个用于描述已发生事件的普通对象。
store.dispatch({type:'COMPLETE_TOO', index: 1})
  • 使用纯函数来执行修改
    为了描述action如何改变state tree,你需要去编写reducers
    reducers只是一些纯函数,它接受先前的stateaction,并且返回新的state
    纯函数的好处:可以复用,可以控制顺序,传入附加参数。

5)redux的状态

(1) state-状态

就是我们传递的数据,那么我们在用Rect开发项目的时候,大致可以把State分为三类

  • DomainDate:可以理解成服务器端端数据,比如:获取用户的信息,商品的列表等等
  • UI State: 决定当前UI决定展示的状态,比如:弹框的显示隐藏,受控组件等等
  • App State:App级别的状态,比如:当前是否请求loading,当前路由信息等可能被多个和组件去使用的到的状态

(2)action-事件

action是把数据从应用(组件)传到store的载体,它是store数据的唯一来源,一般来说,我们可以通过store.dispatch()action传送给store
action的特点

  • action的本质就是一个javascript的普通对象
  • action对象内部必须要有一个type属性来表示要执行的动作
  • 多数情况下,这个type会被定义成字符串常量
  • 除了type字段之外,action的结构随意进行定义
  • 而我们项目中,更多的喜欢用action创建函数(就是创建action的地方)
  • 只是描述了有事情要发生,并没有描述去如何去更新state
//action
{
	type: '字符串常量',
	info: {...},
	isLoading: true
}
//action创建函数
function addAction(params){
	//返回一个action对象
	return {
		type: 'add',
		...params
	}
}

(3)reducer-纯函数

reducer本质就是一个函数,它用来响应发过来的action,然后经过处理,把state发送给store
注意:在reducer函数中,需要return返回值,这样store才能接受到数据,函数会接受两个参数,第一个参数是初始化state,第二个参数action。

const initState = {...}
const rootReducer = (state=initState,action) => {
	...
	return {...}
}

(4)store-联系action和reducer

store 就是把action与reducer联系到一起的对象
主要的职责:

  • 维持应用的state
  • 提供getState()方法获取state
  • 提供dispatch()方法发送action
  • 通过subscribe()来注册监听
  • 通过subscribe()返回值来注销监听
import {creteStore} from "redux"
const store = createStore(传入reducer)

2.Mobx

mobx

3.Recoil

1)RecoilRoot

如果组件中使用Recoil,则可以将RecoilRoot放置在父组件的某个位置。最好将其放在根组件中

2)Atom

一个atom代表一个状态。atom可在任意组件中进行读写。读取atom值的组件隐式订阅了该atom,因此任何atom的更新都将导致该atom的组件重新渲染。

3)Selector

selector代表一个派生状态,派生状态时状态的转换。你可以将派生状态视为将状态传递给以某种方式修改给定状态的纯函数的输出。

4)常用的recoil的hook函数

(1)useRecoilState

当组件同时需要读写状态时,推荐使用该hook。

(2)useRecoilValue

当一个组件需要在不写入state的情况下读取state时,推荐使用该hook。

(3)useSetRecoilState

返回一个setter函数,用来更新可写Recoil state的值,状态变化不会导致组件重新渲染。
当一个组件需要写入而不需要读取state时,推荐使用此hook。
如果组件使用了useRecoilState()来获取setter函数,那么同时它也会订阅更新,并在atomselector更新时重新渲染。使用useSetRecoilState()允许组件在值发生改变时而不用给组件订阅重新渲染的情况下设置值。

5)关于recoil的例子

(1)输入框

src文件夹下的app.js

import {RecoilRoot} from "recoil";
import HomePage from "./pages/HomePage";

export default function App(props) {
  return (
    <div className="App">
      <RecoilRoot>
        <HomePage />
      </RecoilRoot>
    </div>
  );
}

其中store文件夹pages文件夹src文件夹
store文件夹下的index.js

//状态atom,在需要的组件中,直接引入并使用useRecoilState()即可。
import {atom,selector} from "recoil";
export const textState = atom({
	key: 'textState',   //全局下保持唯一性
	default: '',		//初始值
});
//派生状态,在需要的组件中,可以使用useRecoilValue()的hook,
//来读取派生状态即可。
export const charCountState = selector({
	key: "charCountState", //全局下唯一性
	get: ({get}) => {
		const text = get(textState);
		return text.length;
	}
});

pages文件夹下的HomePage组件

import {useRecoilState, useRecoilValue, useSetRecoilState} from "recoil";
import {textState, charCountState} from "../store/";
import TextInput from "./TextInput.js";
import CharacterCount from "./CharacterCount.js";

export default function HomePage(props) {
	return (
		<div>
			<h3>HomePage</h3>
			<TextInput/>
			<CharacterCount/>
		</div>
	);
}

pages文件夹下的TextInput组件

import {useRecoilState} from "recoil";
import {textState, charCountState} from "../store/";
export function TextInput(props) {
	const [text, setText] = useRecoilState(textState);
	const onChange = e => {
		setText(e.target.value);
	};
	return (
		<div>
			<input type="text" value={text} onChange={onChange}/>
			<br/>
			Echo:{text}
		<div>
	);
}

pages文件夹下的CharacterCount组件

import {useRecoilValue} from "recoil";
import {textState, charCountState} from "../store/";
export function CharacterCount(props){
	const count = useRecoilValue(charCountState);
	return (
		<div>
			<p>{count}</p>
		<div>
	);
}

(2)todolist清单

4.对比redux,mobx,recoil

  • redux集中式管理state,而recoilmobx是分散式的
  • recoil目前只适用于hooks函数
  • recoil时facebook开发的,可以使用react内部的调度机制,这是reduxmobx不支持的
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值