react获取全局_React Hooks下的全局状态管理

本文探讨了React Hooks如何用于全局状态管理,包括useState、useEffect、useReducer以及如何结合Redux、新Context API和unstated-next等工具进行状态管理。通过示例展示了如何使用这些Hooks简化组件状态管理,同时对比了不同状态管理方案的适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

React Hooks下的全局状态管理

React Hooks

React Hooks 是 React 16.7.0-alpha 版本推出的新特性,旨在解决组件间共享状态逻辑的问题。

**useState: **允许在 function 组件中,声明和改变状态。在此之前,只有 class 组件可以。(useImmer)

**useEffect: **允许在 function 组件中,抽象地使用 React 的生命周期函数。开发者可以使用更函数式的、更清晰的 hooks 的方式。

使用 hooks 对带有本地状态的 Avatar 组件进行重构说明:

import React, { useState, useEffect } from 'react';

const Avatar = () => {

// 创建 user 状态和修改状态的函数

const [user, setUser] = useState("马飞");

// 默认 componentDidMount/componentDidUpdate 时会触发回调

// 也可以使用第二个参数,指定触发时机

useEffect(() => {

document.title = 当前用户:${user};

});

// 使用 setUser 改变状态

return

setUser("mafeifei")}>{user};

};复制代码useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init);

复制代码

useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法,提供了组件内使用redux的方式管理状态。

以下是用 reducer 重写 useState 一节的计数器示例:

const initialState = {count: 0};

function reducer(state, action){

switch (action.type) {

case 'increment':

return {count: state.count + 1};

case 'decrement':

return {count: state.count - 1};

default:

throw new Error();

}

}

function Counter(){

const [state, dispatch] = useReducer(reducer, initialState);

return (

<>

Count: {state.count}

dispatch({type: 'increment'})}>+

dispatch({type: 'decrement'})}>-

>

);

}复制代码

Redux

作为目前最流行的状态管理框架,Redux在7.1.0版本中也提供了对于Hooks的支持。

API

store和reducer部分和原先保持一致,外层也需要包装Provider

const store = createStore(rootReducer)

ReactDOM.render(

,

document.getElementById('root')

)

复制代码

在获取和更新store数据上,Redux针对Hooks提供了新的API。

useSelector()

const result : any = useSelector(selector : Function, equalityFn? : Function)

// useSelector(state => state.count)

复制代码

selector概念上和connect的mapStateToProps参数相似,将store中的state作为第一个参数,在每次component render时都会调用。在数据的更新上,useSelector会订阅store,当有action执行时会重新调用selector获取最新的数据。和mapStateToProps不同的是useSelector默认使用===比较更新前后的数据,所以提供了第二个参数equalityFn来定制比较函数。

useDispatch

const dispatch = useDispatch()

复制代码

useDiapatch返回dispatch的引用,用来调用action。

useStore()

const store = useStore()

复制代码

useStore会返回Redux中store的引用,可以使用store.getState()获取store中的state。

Demo

reducer可配合immer使用

codesandbox

import React from "react";

import ReactDOM from "react-dom";

import { createStore } from "redux";

import { Provider, useSelector, useDispatch } from "react-redux";

import {produce} from 'immer'

const initState = {

count: 0

};

const reducer = (state = initState, action) => produce(state, draft => {

switch (action.type) {

case "increase": {

draft.count += 1

break

}

case "decrease": {

draft.count += 1

break

}

default:

}

})

const store = createStore(reducer);

const Counter = () => {

const count = useSelector(state => state.count); // useSelector

const dispatch = useDispatch(); // useDispatch

return (

Counter: {count}

dispatch({ type: "increase" })}>Increase

dispatch({ type: "decrease" })}>Decrease

)

}

const App = () => {

return (

);

}

const rootElement = document.getElementById("root");

ReactDOM.render(

,

rootElement

);复制代码

New Context API + Hooks

useContext

React Hooks提供了useContext来访问context,可以在使用 Consumer 的时候不必包裹 Children

import React, { useContext } from 'react';

function Display(){

const value = useContext(NumberContext);

return

The answer is {value}.
;

}

复制代码

useReducer

useReducer是hooks提供的针对复杂场景替代useState管理状态的API,提供了action和reducer的方式来管理组件内状态,它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。

const initialState = {count: 0};

function reducer(state, action){

switch (action.type) {

case 'increment':

return {count: state.count + 1};

case 'decrement':

return {count: state.count - 1};

default:

throw new Error();

}

}

function Counter(){

const [state, dispatch] = useReducer(reducer, initialState);

return (

<>

Count: {state.count}

dispatch({type: 'increment'})}>+

dispatch({type: 'decrement'})}>-

>

);

}复制代码

文章(link)提供了一种context配合hooks实现全局状态管理的一种思路,相较于纯context,配合hooks的useReducer提供了更为强大的状态管理能力。

import React, {createContext, useContext, useReducer} from 'react';

export const StateContext = createContext();

export const StateProvider = ({reducer, initialState, children}) =>(

{children}

);

export const useStateValue = () => useContext(StateContext);复制代码

首先新建一个StateContext,然后再StateContext的Provider中将context的值设置为useReducer(reducer, initialState),这样当调用action执行reducer后,context的值也将发生变化,似的引用context值得组件更新。由useReducer也保证了只有在数据变化是才会更新组件。

在访问context数据方便也做了一层useStateValue hooks封装,不需要在每个组件里调用useContext。

demo

import React, { createContext, useContext, useReducer } from "react";

import { render } from "react-dom";

import { produce } from "immer";

const StateContext = createContext();

const StateProvider = ({ reducer, initialState, children }) => (

{children}

);

const useStateValue = () => useContext(StateContext);

function App() {

const initialState = {

count: 0

};

const reducer = (state = initialState, action) =>

produce(state, draft => {

switch (action.type) {

case "increase": {

draft.count += 1;

break;

}

case "decrease": {

draft.count += 1;

break;

}

default:

}

});

return (

);

}

const Count = () => {

const [{ count }, dispatch] = useStateValue();

return (

Counter: {count}

dispatch({ type: "increase" })}>Increase

dispatch({ type: "decrease" })}>Decrease

);

};

const rootElement = document.getElementById("root");

render(, rootElement);复制代码

unstated-next

unstated是react社区中比较流行的轻量级的状态管理工具,在api设计的时候沿用react的设计思想,能够快速的理解和上手。

Unstated抛出三个对象,分别是Container、Subscribe和Provider。

Unstated会使用React.createContext来创建一个StateContext对象,用来进行状态的传递。

unstated demo

import React from 'react';

import { render } from 'react-dom';

import { Provider, Subscribe, Container } from 'unstated';

type CounterState = {

count: number

};

class CounterContainer extends Container{

state = {

count: 0

};

increment() {

this.setState({ count: this.state.count + 1 });

}

decrement() {

this.setState({ count: this.state.count - 1 });

}

}

function Counter(){

return (

{counter => (

counter.decrement()}>-

{counter.state.count}

counter.increment()}>+

)}

);

}

render(

,

document.getElementById('root')

);

复制代码

随着Hooks的推出,Unstated也推出了符合hooks api的新一代状态管理库unstated-next,在API设计上延续了Unstated贴近react操作的风格,使用自定义hooks来管理状态。

createContainer(useHook)

创建container,接受一个封装状态的自定义hook参数

import { createContainer } from "unstated-next"

function useCustomHook(){

let [value, setValue] = useState()

let onChange = e => setValue(e.currentTarget.value)

return { value, onChange }

}

let Container = createContainer(useCustomHook)

复制代码

保留了unstated中的Provider

function ParentComponent(){

return (

)

}复制代码

useContainer(Container)

在组件内通过useContainer获取自定义hook中的状态和操作

import { useContainer } from "unstated-next"

function ChildComponent(){

let input = useContainer(Container)

return

}复制代码

Demo

import { render } from "react-dom";

import React, { useState } from "react";

import { createContainer } from "unstated-next";

function useCounter(initialState = 0){

let [count, setCount] = useState(initialState);

let increase = () => setCount(count + 1);

let decrease = () => setCount(count - 1);

return { count, increase, decrease };

}

let Counter = createContainer(useCounter);

function App(){

let counter = Counter.useContainer();

return (

Counter: {counter.count}

Increase

Decrease

);

}

render(

,

document.getElementById("root")

);复制代码

mobx-react-lite

作为流行度仅此于Redux的状态管理组件也针对hooks进行了匹配,推出了新一代的状态管理库mobx-react-lite,不再使用inject将store注入component,而是配合react的新context api将store放入context管理。

demo

import { observable } from 'mobx'

import { Observer, useObserver, observer } from 'mobx-react' // 6.x or mobx-react-lite@1.4.0

import ReactDOM from 'react-dom'

const person = observable({

name: 'John',

})

// named function is optional (for debugging purposes)

const P1 = observer(function P1({ person }) {

return

{person.name}

})

const P2 = ({ person }) => {() =>

{person.name}

}

const P3 = ({ person }) => {

return useObserver(() =>

{person.name}

)

}

ReactDOM.render(

)

setTimeout(() => {

person.name = 'Jane'

}, 1000)

复制代码

比较

Redux是社区最流行的状态管理工具,生态较好,支持middleware,提供了可预测的状态管理,但需要写大量的模板代码,且包体积在状态管理工具中相对较大,适合大型项目

context + hooks提供了基本的状态管理功能,配合hooks中的useReducer可以支持大部分redux提供的功能,且不需要引入其他库,适合全局状态较简单的项目

unstated将状态和操作封装在container中,优点是在风格上比redux更贴近react的操作方式,也更容易上手,仅有200b,但是相比context+useReducer的方式没什么优势,除非原来就使用了unstated的项目,否则并不推荐。

mobx-react-lite延续了mobx的优点,将状态维护在observable的对象中管理,采用代理的方式,支持直接操作对象,相比redux在代码写法上较为简洁,但对于大型项目,mobx较为灵活的方式不如reducer action->reducer->state的流程更清晰,比较适合中小型项目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值