React状态管理 | 青训营笔记
什么是状态管理
状态管理本身,解决的就是这种潜逃地狱的问题,解决的是跨层级组件之间的数据通信和状态共享
状态管理工具的本质:管理共享内存中的状态
- 共享内存
- 管理状态
- 页面通信
- 组件通信
- 刷新失效?
详细定义:单页应用的各个组件本身是共享内存的,如果将状态保存在内存中,就可以读写统一内存中的变量,,从而达到状态共享的目的。
状态管理工具简介
- React自带:Local State(props) 和 context
- 单向数据流:Flux、Redux
- 双向数据绑定:Mobx
- 原子型状态管理:Recoil、Jotai
- 异步操作密集型:Rxjs
1、Local State(props):组件级别的局部状态
import {useState} from 'react'
const Hello = () => {
const [name, setName] = useState('tom')
return <>Hello, {name}</>
}
只在Hello组件中生效,当组件创建时初始化和生效,组件销毁时失效
但是当一个父组件嵌套十几层子组件的时候,子页面和子页面之间的通信,React本身提供了Context
2、Context
function useCounter() {
// 状态、属性
let [count, setCount] = useState(0)
let decrement = () => setCount(count-1)
let increment = () => setCount(count+1)
return { count, decrement, increment }
}
let Counter = createContext(null)
function CounterDisplay() {
let counter = useContext(Counter)
return <div>
<button onClick={counter.decrement}>-</button>
<button onClick={counter.decrement}>-</button>
<p>{counter.count}</p>
</div>
}
function App() {
let counter = useCounter()
return
<Counter.Provider value={counter}>
<CounterDisplay />
<OtherDisplay />
</Counter.Provider>
}
OtherDisplay 组件中没有用到context里的value,但是当context值变换的时候,OtherDisplay也会重新渲染
- Context相当于他全局变量,难以追溯数据的变更情况
- 使用Context的组件内部耦合度太高,不利于组件的复用和单元测试
- 会产生不必要的更新,会穿透memo和dependicies
- 多个Context会存在层层嵌套的问题
3、Redux
在Redux上解构了Action和Dispatcher
export default addTodo(text) {
return {
type: ActionTypes.ADD,
text: text
}
}
let action = {
type: 'add'
}
dispatcher.dispatch(action)
dispatcher.register((action) => {
switch(action.type) {
case 'add':
...
break;
}
})
- 单一数据源:在redux中,整个应用的全局State,都会保存在一个store中,一个单一数据源store tree 也简化了应用的调试和监控
- store中的state是只读的:我们不能直接修改store中的state,唯一能改变state的方式就是通过action
- 使用纯函数来执行修改:接受纯函数来接受action,该纯函数叫reducer,可以改变store中的state