react全局状态管理_react的状态管理

近两年前端技术的发展如火如荼,大量的前端项目都在使用或转向 Vue 和 React 的阵营, 由前端渲染页面的单页应用占比也越来越高,这就代表前端工作的复杂度也在直线上升,前端页面上展示的信息越来越多也越来越复杂。我们知道,任何状态都需要进行管理,那么今天我们来聊聊前端状态管理。

前端状态管理第三方出名的库有: Flux、Redux、Vuex、Mobx 等

这里专讲react的状态管理演变

redux

开发者门接触最多的应该就是redux,这里从浅入深的来逐步学习吧

1 .单纯的使用纯redux库,参考redux1

// Action

export const commonType = {//action type

SET_AGE: 'SET_AGE'

}

export function setAge(payload: any) {//action creator

return {

type: commonType.SET_AGE,

payload

}

}

// reducer

const commonReducer = (state = initialState, action: any) =>{

switch (action.type) {

case commonType.SET_AGE:

return { ...state, ...action.payload };

default:

return state;

}

}

const allReducer = combineReducers({

common:commonReducer

})

// store

import { createStore } from 'redux'

let store = createStore(allReducer);

// 使用(订阅)

import store from '../redux/store'

export default class App extends React.Component {

constructor(props: any) {

super(props);

this.state = {iptVal:0};

}

componentDidMount() {

store.subscribe(() =>{

let {common:{age:iptVal}}= store.getState();

this.setState({iptVal});

})

}

render() {

return (

{this.state.iptVal}
);

}

}

// 使用(广播)

import store from '../redux/store'

export default class A extends React.Component {

constructor(props: any) {

super(props);

this.state = {iptVal:0};

}

componentDidMount() {

store.subscribe(() =>{

let {common:{age:iptVal}}= store.getState();

this.setState({iptVal});

})

}

iptChange = (e: any) =>{

store.dispatch(actions.setAge({

age:e.target.value

}));

}

render() {

const { iptVal } = this.state;

return (

<>

{iptVal}

>

)

}

}

缺点很明显,需要在改变和监听数据的地方都引入store,并手动与组件关联,因此有了第2种方式

2 .使用redux + react-redux方式, 参考redux2

// Action

export const commonType = {//action type

SET_AGE: 'SET_AGE'

}

export function setAge(payload: any) {//action creator

return {

type: commonType.SET_AGE,

payload

}

}

// reducer

import { combineReducers } from 'redux';

const commonReducer = (state = initialState, action: any) =>{

switch (action.type) {

case commonType.SET_AGE:

return { ...state, ...action.payload };

default:

return state;

}

}

const allReducer = combineReducers({

common:commonReducer

})

// store

import { createStore } from 'redux'

let store = createStore(allReducer);

// 使用(订阅)

import { connect } from 'react-redux'

class App extends React.Component {

constructor(props: any) {

super(props);

}

render() {

return (

{this.props.iptVal}
);

}

}

export default connect(

(state: any) => {

return {iptVal: state.common.age}

},null

)(App);

// 使用(广播)

import { connect } from 'react-redux'

class A extends React.Component {

constructor(props: any) {

super(props);

}

render() {

return (

<>

{this.props.iptVal}

>

)

}

}

export default connect(

(state: any) => {

return {iptVal: state.common.age}

},

(dispatch: any)=>{return {

iptChange(e: any){

dispatch(actions.setAge({

age:e.target.value

}))

}

}}

)(A);

这样就不用手动处理全局状态与react的关系了,如果你了解注解(装饰器),看起来代码就更简单了,反正我是没有配置成功,你可以试试

不过action creator和reducer创建起来好费劲。action creator要写大量的重复代码,reducer遍地的switch case,所以便有了第3种方式。

3 .redux + react-redux + redux-actions, 源代码在redux3

// Action

import { createAction } from 'redux-actions';

export const commonType = {SET_AGE: 'SET_AGE'};//action type

export const setAge = createAction(commonType.SET_AGE);//action creator

// reducer

import { combineReducers } from 'redux';

import { handleActions } from "redux-actions";

const initialState = {age: 0}; //初始化state

let reducers = {

[commonType.SET_AGE](state: any, action: any){

let { payload } = action;

return {...state,...payload};

}

};

const commonReducer = handleActions(reducers,initialState);

const allReducer = combineReducers({

common:commonReducer

})

// store

import { createStore } from 'redux'

let store = createStore(allReducer);

// 使用(订阅)

import { connect } from 'react-redux'

class App extends React.Component {

constructor(props: any) {

super(props);

}

render() {

return (

{this.props.iptVal}
);

}

}

export default connect(

(state: any) => {

return {iptVal: state.common.age}

},null

)(App);

// 使用(广播)

import { connect } from 'react-redux'

class A extends React.Component {

constructor(props: any) {

super(props);

}

render() {

let {iptVal,iptChange} = this.props;

return (<>

{iptVal}

>)

}

}

export default connect(

(state: any) => {

return {iptVal: state.common.age}

},

(dispatch: any)=>{return {

iptChange(e: any){

dispatch(actions.setAge({

age:e.target.value

}))

}

}}

)(A);

这样做效果已经很好了,至少在hooks来之前,这是大家普遍使用的方法来管理react的全局状态。但是hooks之后,我推荐如下,原因是 不用引入任何第三方包

React.Context

使用作用域之React.Context,这个学过java的人都知道,此对象是贯穿整个应用的。通过注入便监听 Context来达到redux同样的效果,好不用引入第三方包。参考context

// Context

const commonContext = React.createContext({ //初始化,不具体实现

age: 0,

setAge: (age: number) => {}

});

// 使用(注入需要订阅的组件)

import {useState} from 'react';

import CommonContext from './context';

export default const App = () => {

const [ age, setAges ] = useState(10);

let myValue = {

age,setAge(age: number){setAges(age)}

};

return (<>

{age}

>);

}

// 使用(发起广播)

import * as React from 'react';

import { useContext } from 'react';

import commonContext from '../context';

export default const B =()=> {

const commonCtx = useContext(commonContext);

const onChange = (e: any)=>{

commonCtx.setAge(e.target.value)

};

return (<>

{commonCtx.age}

>)

}

// 使用(订阅监听)--函数式组件使用hooks订阅

import * as React from 'react';

import { useContext } from 'react';

import commonContext from '../context';

export default const A = (props: any) => {

const commonCtx = useContext(commonContext);

return (

{commonCtx.age}
)

}

// 使用(订阅监听)--类组件两种方式订阅

import * as React from 'react'

import commonContext from '../context';

export default class C extends React.Component {

static contextType = commonContext;

constructor(props: any){

super(props);

}

render(){

return (

// 在没有useContext的hooks之前,通常这样取得和监听Context

<>

方式1:this.context,使用Class.contextType你可以在任何生命周期中访问到this.context:

{this.context.age}

方式2:Consumer, 让你在函数式组件中完成订阅 context:

{commonCtx=>

{commonCtx.age}
}

>

)

}

};

如果只是用Context,功能能实现,但是还不是很灵活,比如动态的value(state和reducer)你得自己手动创建并关联,所以便有了如下办法。

React.Context 和 hooks之useReducer

这是目前react官方最推荐的使用方式,也是本文一路想引申的,如果想单独看useReducer的使用方式请看useReducer,最终结合版看useReducerContext

// Context

const commonContext: any = React.createContext(null);

//action

export const commonType = {

SET_AGE:'SET_AGE'

}

export const setAge = (payload: any) =>{

return {

type: commonType.SET_AGE,

payload

}

}

//reducer

const initialState: any = {age: 0};

function reducer(state: any, action: any) {

switch (action.type) {

case commonType.SET_AGE:

let { payload } = action;

return {...state,...payload};

default:

throw new Error();

}

}

export {

initialState,

reducer

};

//使用(注入需要订阅的组件)

import * as React from 'react';

import A from './components/a';

import B from './components/b';

import C from './components/c';

import {useReducer} from 'react';

import { reducer, initialState } from './redux/reducer/common';

import CommonContext from './context';

export default () => {

const myValue = useReducer(reducer, initialState);

return (

{myValue[0].age}

);

}

// 使用(发起广播)

import * as React from 'react';

import { useContext } from 'react';

import commonContext from '../context';

export default const B =()=> {

const [state,dispatch] = useContext(commonContext);

const onChange = (e: any)=>{

let payload = {

age: e.target.value

}

dispatch(setAge(payload))

};

return (<>

{state.age}

>)

}

// 使用(订阅监听)--函数式组件使用hooks订阅

import * as React from 'react';

import { useContext } from 'react';

import commonContext from '../context';

export default const A = (props: any) => {

const [state] = useContext(commonContext);

return (

{state.age}
)

}

// 使用(订阅监听)--类组件两种方式订阅

import * as React from 'react'

import commonContext from '../context';

export default class C extends React.Component {

static contextType = commonContext;

constructor(props: any){

super(props);

}

render(){

return (

// 在没有useContext的hooks之前,通常这样取得和监听Context

<>

{/* 方式1:this.context,使用Class.contextType你可以在任何生命周期中访问到this.context */}

{this.context[0].age}

{/* 方式2:Consumer, 让你在函数式组件中完成订阅 context */}

{([state]:any)=>{

return

{state.age}

}}

>

//总结:使用useContext()时候我们可以不需要使用Consumer了,看你喜欢哪个了

)

}

};

demo地址:https://gitee.com/dshvv/reactStatus

这只是状态管理最基本的用法,还有特殊情况 比如异步action等等,没有专门讲,感兴趣的可以去看看,不过建议先看最普通和基础的

你可能感兴趣的:(react全局状态管理)