react全局状态管理_使用 react 的 hooks 进行全局的状态管理

使用 react 的 hooks 进行全局的状态管理

React 最新正式版已经支持了 Hooks API,先快速过一下新的 API 和大概的用法。

// useState,简单粗暴,setState可以直接修改整个state

const [state,setState] = useState(value);

// useEffect,支持生命周期

useEffect(()=>{

// sub

return ()=>{

// unsub

}

},[]);

// useContext,和 React.createConext() 配合使用。

// 父组件使用 Context.Provider 生产数据,子组件使用 useContext() 获取数据。

const state = useContext(myContext);

// useReducer,具体用法和redux类似,使用dispatch(action)修改数据。

// reducer中处理数据并返回新的state

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

// useCallback,返回一个memoized函数,第二个参数类似useEffect,只有参数变化时才会更改。

const memoizedCallback = useCallback(

() => {

doSomething(a, b);

},

[a, b],

);

// useMemo,返回一个memoized值,只有第二个参数发生变化时才会重新计算。类似 useCallback。

// useCallback(fn,inputs) 等效 useMemo(() => fn,inputs)。

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])

// useRef,返回一个可变的ref对象

const refContainer = useRef(initialValue);

// useImperativeMethods,详情自行查阅文档

// useMutationEffect,类似useEffect,详情自行查阅文档

// useLayoutEffect,类似useEffect,详情自行查阅文档

一开始以为使用 useState 分离数据层 和 UI 层,就可以达到数据共享了,后来发现想的太简单了。分离只是逻辑共享,数据都是独立的。

后来发现有个 useReducer  似乎和 redux 很像,然而本质上,还是 useState 实现的。

再继续探索发现,基于useContext,同时配合useReducer一起使用。

但是,这个方案的缺陷是,当数据太大,组件太多,会直接导致渲染性能下降。

每一次state的变化,都会从顶层组件传递下去,性能影响比较大。

当然也有一些优化手段,比如使用memo()或者useMemo(),又或者拆分更细粒度的context,对应不同的数据模块,再包装成不同的ContextProvider,只是这样略显繁琐了。

后面,终于找到一位大神的作品,经过简单的修改后得出一个可以使用的办法:

import { useState,useEffect } from ‘react‘;

const isFunction = fn => typeof fn === ‘function‘;

const isObject = o => typeof o === ‘object‘;

const isPromise = fn => {

if (fn instanceof Promise) return true;

return isObject(fn) && isFunction(fn.then);

};

// Model 类

class Model {

constructor({initialState,actions}){

this.state = initialState;

this.actions = {};

this.queue = [];

Object.keys(actions).forEach((name)=>{

this.actions[name] = (arg)=>{

const res = actions[name].call(this,this.state,arg);

if(isPromise(res)){

Promise.resolve(res).then((ret)=>{

this.state = ret;

this.onDataChange();

});

}else{

this.state = res;

this.onDataChange();

}

}

});

}

useStore(){

const [, setState] = useState();

// 使用useEffect实现发布订阅

useEffect(() => {

const index = this.queue.length;

this.queue.push(setState); // 订阅

return () => { // 组件销毁时取消

this.queue.splice(index, 1);

};

},[]);

return [this.state, this.actions];

}

onDataChange(){

const queues = [].concat(this.queue);

queues.forEach((setState)=>{

setState(this.state); // 通知所有的组件数据变化

});

}

}

// models/user.js

const sleep = async t => new Promise(resolve => setTimeout(resolve, t));

const initialState = {};

const actions = {

async setUserInfo(){

await sleep(2000);

return Promise.resolve({name:"mannymu",age:18});

},

setAge(state,age){

return Object.assign({},{...state,age});

},

setName(state,name){

return Object.assign({},{...state,name});

},

loginOut(){

return null;

}

}

const user = new Model({

initialState,

actions

});

// 组件

import {useStore} from ‘../models/user‘;

const Person = ()=>{

const [state,actions] = useStore();

return (

My name is {state.name}.

actions.setName(‘han meimei.‘)}>btn1

)

};

这样就可以使用简单的代码,管理复杂的状态了。同时支持异步。

通过查看那位大佬在 github 上面的完整版状态管理插件源码。其基于上面的代码基本原理。做了 Proxy 的封装,就可以像  vue 一样,直接修改 this.xxx 来更新视图层。

最后,附上我的本地文件夹分类:

5ff6d33a943cc905d1d587e69f4abfba.png

其中 store.js 里面,是上面的 Model 类。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React HooksReact 16.8 中新增的特性,它允许函数组件中使用 state 和其他 React 特性,从而使函数组件具有类组件的能力。 使用 React Hooks 需要先引入 React 的 useState、useEffect 等钩子函数,然后在函数组件中使用它们。 useState useState 是最常用的 Hook 之一,它可以让我们在函数组件中使用 state。useState 接收一个初始值作为参数,并返回一个数组,数组的第一个元素是当前 state 的值,第二个元素是更新 state 的函数。 例如,下面的代码在函数组件中使用了 useState 来保存一个计数器: ``` import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } ``` useEffect useEffect 是另外一个常用的 Hook,它可以在函数组件中使用副作用。副作用包括数据获取、订阅或手动修改 DOM 等操作。useEffect 接收一个函数作为参数,该函数会在组件渲染完成后执行。 例如,下面的代码使用 useEffect 来更新页面标题: ``` import React, { useState, useEffect } from 'react'; function PageTitle() { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } ``` useContext useContext 可以让我们在函数组件中使用 Context。Context 是一种在组件树中传递数据的方法,它可以避免通过 props 层层传递数据。 例如,下面的代码使用 useContext 来获取全局的主题: ``` import React, { useContext } from 'react'; const ThemeContext = React.createContext('light'); function ThemeButton() { const theme = useContext(ThemeContext); return ( <button style={{ background: theme.background, color: theme.foreground }}> I am styled by theme context! </button> ); } ``` 使用 useContext 前需要先创建一个 Context,可以使用 React.createContext 方法来创建。 除了上述三个 Hook,还有 useReducer、useCallback、useMemo、useRef 等 Hook 可以使用使用这些 Hook 可以让函数组件更加强大和灵活。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值