我的编程空间,编程开发者的网络收藏夹
学习永远不晚

基于ReactContext实现一个简单的状态管理的示例代码

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

基于ReactContext实现一个简单的状态管理的示例代码

前言

在大多数情况下,我们开发项目都需要一个状态管理,方便我们在全局共享状态库,在React生态里比较流行的几个库

redux、mobx、recoil

但是对于小项目,我们完全可以自己封装一个状态管理,减少一个包的安装就可以减小打包以后的项目体积。 主要分两步:

  • 封装一个顶层组件提供数据
  • 子组件获取数据和更新数据

封装一个父组件用来包裹其他子组件

stores/index.js 文件中首先需要调用 createContext

export const MyContext = React.createContext({list: [], data: null, time: Date.now()});

createContext 中的参数是默认值,只有当组件所处的树中没有匹配到 Provider 时,其参数才会生效。

每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。

创建一个 Context 对象。当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中匹配离自身最近的Provider,并从中读取到当前的 context 值。

context 可以设置一个displayName 的属性, 可以方便在React DevTool 对该context调试。

MyContext.displayName = 'MyManagementDisplayName';

Provider 接收一个 value 属性,传递给消费组件。 Context 能让你将这些数据向组件树下所有的组件进行“广播”,所有的组件都能访问到这些数据,也能访问到后续的数据更新。

这里我们封装一个父组件用来包裹其他子组件。

import { createContext, useReducer } from 'react';

// 纯函数reducer
function reducer(state, action) {
    // action包括 具体的类型type,
    // 除了 `type` 之外,action 对象的结构其实完全取决于你自己。
    // 这里使用了payload代表dipatch传过来的数据
    switch(action.type) {
        case 'list':
            return ({...state, list: action.payload});
        case 'data':
            return ({...state, data: action.payload});
        case 'time':
            return ({...state, time: action.payload});
        default:
            return state;
    }
}
const list = [{num: 0, key: 0}, {num: 1, key: 1}, {num: 2, key: 2}];
export const MyContext = createContext({list: [], data: null, time: Date.now()});

function ContextProvider({children}) {
    const [state, dispatch] = useReducer(
        reducer,
        {list: list, data: null, time: Date.now()}
    );

    const value = {
        state,
        dispatch
    }
    return <MyContext.Provider value={value}>
        {children}
    </MyContext.Provider>
}

export default ContextProvider;

这里用到了useReducer, 用过redux的同学一定非常熟悉,这是因为redux的作者 dan abramov 加入了react开发团队, 是react的主要开发者。 第一个参数是一个处理数据的纯函数,第二个参数是 initialValue。 useReducer还有另一种用法可以接受函数作为第三个参数,可以惰性地创建初始 state,这不是本文的重点,感兴趣的同学可以自行查询文档学习。

在入口文件index.js中 用 ContextProvider 包裹 App 组件

import ReactDOM from 'react-dom';
import App from './App';
import './styles/index.less';

import ContextProvider from './stores';
ReactDOM.render(
    <ContextProvider><App /></ContextProvider>,
    document.getElementById('root')
);

子组件如何获取数据呢

有3种方式

  • Class Component 内获取(本方法仅能订阅 1 个 context)
  • context.Consumer
  • useContext

class Component 方式

import {MyContext} from '@/store';

class MyClass extends React.Component {
  static contextType = MyContext;
  // 引入的MyContext 赋值给静态属性 contextType后,
  // React可以让你使用 `this.context` 来获取最近 Context 上的值。
  componentDidMount() {
    let value = this.context;
    
  }
  componentDidUpdate() {
    let value = this.context;
    
  }
  componentWillUnmount() {
    let value = this.context;
    
  }
  render() {
    let value = this.context;
    
  }
}

context.Consumer

<context.Consumer>
  {value => /* 基于 context 值进行渲染* /}
</context.Consumer>

useContext

这是使用 hook 方式, 也是目前最流行的用法,后面的例子主要使用这个方式来演示。 因为我们要在很多需要全局状态的子组件使用,所以我们可以封装一下。

在 hooks/useStores.js

import {MyContext} from '@/stores';
import React from 'react';

// 封装代码以复用
const useStores = () => React.useContext(MyContext);

export default useStores;

下面我们通过两个组件,分别演示 获取数据并展示更新全局数据

views/footer/index.js
在此组件里获取全局数据并展示

import { useEffect } from 'react';
import useStores from '../../hooks/useStores';

function Footer() {
  const { state } = useStores();
  const { time, list } = state;
  useEffect(() => {
    console.log('Footer page rendered!!!')
  })
  return (
    <div style={{ height: 200 }}>
      <div>time now is {time}</div>
      <div>
        list is
        {list.map((item) => (
          <span 
              style={{
                  background: 'pink',
                  padding: '0 10px',
                  border: '1px solid',
                  marginRight: '10px'
              }}
              key={item.key}
          >
              {item.num}
          </span>
        ))}
      </div>
    </div>
  );
}

export default Footer;

views/header/index.js

我们在此组件里更新全局数据

import useStores from '../../hooks/useStores';
import { Link } from 'react-router-dom';
import { useEffect } from 'react';

function Header() {
  // 解构获取 dispatch 方法
  const { dispatch } = useStores();
  const handleList = () => {
    const payload = [...new Array(3)].map(() => {
      const key = Math.random();
      const num = Math.floor(key * 100);
      return ({
        key, num
      });
    })
    // 更新数据,订阅状态的组件都会获取更新通知并取到最新数据
    dispatch({ type: "list", payload });
  };
  return (
    <div style={{ height: 100 }}>
      <button onClick={() => dispatch({ type: 'time', payload: Date.now() })}>
        time
      </button>
      <button onClick={handleList}>list</button>
    </div>
  );
}

export default Header;

点击 header 中的按钮,footer 里的 time list 都会响应改变,获取到最新的值并渲染展示。

总结

我们通过封装顶层组件提供全局数据,子组件获取和更新数据, 完全基于 React 实现了一个简单的状态管理。

当然 Context 是可以嵌套多层的,同学们可以自行尝试

参考

  • React Context
  • React useReducer

 到此这篇关于基于React Context实现一个简单的状态管理的示例代码的文章就介绍到这了,更多相关React Context状态管理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

基于ReactContext实现一个简单的状态管理的示例代码

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

基于Python实现一个简单的学生管理系统

这篇文章主要为大家详细介绍了如何利用python实现简单的学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
2022-12-31

java实现一个简单的网络爬虫代码示例

目前市面上流行的爬虫以python居多,简单了解之后,觉得简单的一些页面的爬虫,主要就是去解析目标页面(html)。那么就在想,java有没有用户方便解析html页面呢?找到了一个jsoup包,一个非常方便解析html的工具呢。使用方式也非
2023-05-30

基于Echarts实现绘制立体柱状图的示例代码

这篇文章主要为大家详细介绍了如何基于Echarts实现绘制立体柱状图的功能,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
2023-02-23

基于Go语言实现的简易api网关的示例代码

浏览器的请求去请求目标地址,然后获得结果它再发送给浏览器。对于Go语言来说,实现转发只需要简单的一行代码即可实现,如下所示:httputil.NewSingleHostReverseProxy(address) 基于此功能,进行简单包装,实
2022-06-07

基于Python怎样实现一个简易的数据管理系统

这期内容当中小编将会给大家带来有关基于Python怎样实现一个简易的数据管理系统,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。为了方便的实现记录数据、修改数据没有精力去做一个完整的系统去管理数据。因此,在
2023-06-22

基于Java实现的一层简单人工神经网络算法示例

本文实例讲述了基于Java实现的一层简单人工神经网络算法。分享给大家供大家参考,具体如下:先来看看笔者绘制的算法图:2、数据类import java.util.Arrays;public class Data { double[] vec
2023-05-30

Java如何通过动态代理实现一个简单的拦截器操作

这篇文章主要介绍“Java如何通过动态代理实现一个简单的拦截器操作”,在日常操作中,相信很多人在Java如何通过动态代理实现一个简单的拦截器操作问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java如何通过动
2023-06-20

Java怎么通过动态代理实现一个简单的拦截器操作

本文小编为大家详细介绍“Java怎么通过动态代理实现一个简单的拦截器操作”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java怎么通过动态代理实现一个简单的拦截器操作”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧
2023-06-17

编程热搜

目录