Taro React ---- 在函数组件或类组件中访问上下文(Context)中的值

1. 解决问题的场景

项目是开发好几年了,当时采用的是类组件开发。现在新增需求,新增需求使用的函数组件,组件涉及的层级比较多,如果直接组件传值,比较麻烦。但是单独为这次的需求新增 redux 的引入又觉得没必要。然后在即需要一个页面全局状态统一管理的地方,又不希望进行组件一级一级的传值,不方便维护。最后想到了访问上下文(Context)中的值的方法解决问题。

1. 方案一:父组件为类组件访问上下文

2. 父组件为类组件访问上下文

  1. ClassCreateContext 创建上下文;
  2. HookChildContext 函数组件使用 useContext 访问上下文;
  3. ClassChildContext 类组件使用 static contextType 访问上下文;
  4. ClassConsumerContext 类组件使用 <XxxContext.Consumer> 访问上下文;
  5. 父组件 count 变量;
  6. 父组件修改 count 的操作函数 updateCount;
  7. 创建上下文并提供值 ClassCreateContext.Provider。
import React, { Component } from "react";
import Taro from "@tarojs/taro";
import { View } from "@tarojs/components";
import { ClassCreateContext } from './classCreateContext';
import HookChildContext from './hookChildContext';
import ClassChildContext from './classChildContext';
import ClassConsumerContext from './classConsumerContext';

class ClassContext extends Component {
  constructor(props) {
    super(props);
  }
  state = {  
    count: 0
  }
  // 修改count的值
  updateCount = (type = 'add') => {
    let { count } = this.state;
    count = {
      'add': () => {
        return ++count
      },
      'minus': () => {
        return --count
      }
    }[type]?.()
    this.setState({count})
  }
  render() { 
    let { count } = this.state;
    return <View>
      {/* 类组件的父组件的变量显示和操作 */}
      <View>父组件 count: {count}</View>
      <View className='rui-flex-ac'>
        <View 
          className='rui-fg rui-flex-cc' 
          onClick={this.updateCount.bind(this,'add')}>加</View>
        <View 
          className='rui-fg rui-flex-cc'
          onClick={this.updateCount.bind(this,'minus')}>减</View>
      </View>
      {/* 创建上下文并提供值 */}
      <ClassCreateContext.Provider value={{ count, updateCount: this.updateCount }}>
        {/* 类组件中使用函数组件访问上下文 */}
        <HookChildContext/>
        {/* 类组件中使用类组件使用 static contextType 访问上下文 */}
        <ClassChildContext/>
        {/* 类组件中使用类组件使用 <XxxContext.Consumer> 访问上下文 */}
        <ClassConsumerContext/>
      </ClassCreateContext.Provider>
    </View>;
  }
}

export default ClassContext;

3. 特别注意类组件的操作函数

  // 修改count的值
  updateCount = (type = 'add') => {
    let { count } = this.state;
    count = {
      'add': () => {
        return ++count
      },
      'minus': () => {
        return --count
      }
    }[type]?.()
    this.setState({count})
  }

类组件的父组件的操作函数必须使用箭头函数,因为类组件涉及到函数内部 this 的指向问题,当然我们也可以使用 bind、call、aplly 来解决这个问题,但是我认为此处直接使用箭头函数,直接指向的是当前类组件,这样我们就不用关心在子组件调用操作方法时 this 的指向问题!!!

4. 类组件创建上下文

classCreateContext.js

import { createContext } from "react";
// 创建类组件的上下文
export const ClassCreateContext = createContext({});

5. 函数组件实现访问上下文和修改上下文值 HookChildContext

  1. 引入创建的上下文 ClassCreateContext;
  2. 使用 useContext 访问上下文的值和修改值得操作方法;
  3. 在组件 HookChildContext 中展示访问的上下文值 count;
  4. 在组建 HookChildContext 中操作访问的上下文值的方法 updateCount。
import { View, Text, Image } from '@tarojs/components';
import { useContext } from 'react';
import { ClassCreateContext } from './classCreateContext';

const HookChildContext = (props) => {
  let { count, updateCount } = useContext(ClassCreateContext)
  return <View>
    <View>函数组件【HookChildContext】</View>
    <View>获取上下文 count: {count}</View>
    <View>修改父组件的 count</View>
    <View className='rui-flex-ac'>
      <View 
        onClick={updateCount.bind(null, 'add')}
        className='rui-flex-cc rui-fg'>hook 加</View>
      <View 
        onClick={updateCount.bind(null, 'minus')}
        className='rui-flex-cc rui-fg'>hook 减</View>
    </View>
  </View>
}
export default HookChildContext;

6. 类组件实现访问上下文和修改上下文值 ClassChildContext

  1. 引入创建的上下文 ClassCreateContext;
  2. 使用 static contextType 访问上下文的值和修改值得操作方法;
  3. 在组件 ClassChildContext 中展示访问的上下文值 count;
  4. 在组建 ClassChildContext 中操作访问的上下文值的方法 updateCount。
import React, { Component } from "react";
import Taro from "@tarojs/taro";
import { View } from "@tarojs/components";
import { ClassCreateContext } from './classCreateContext';

class ClassChildContext extends Component {
  static contextType = ClassCreateContext;
  constructor(props) {
    super(props);
  }
  state = {  }
  render() { 
    let { count, updateCount } = this.context;
    return <View>
      <View>类组件【ClassChildContext】</View>
      <View>获取上下文 count: {count}</View>
      <View>修改父组件的 count</View>
      <View className='rui-flex-ac'>
        <View 
          onClick={updateCount.bind(null, 'add')}
          className='rui-flex-cc rui-fg'>class 加</View>
        <View 
          onClick={updateCount.bind(null, 'minus')}
          className='rui-flex-cc rui-fg'>class 减</View>
      </View>
    </View>;
  }
}

export default ClassChildContext;

7. 类组件实现访问上下文和修改上下文值 ClassConsumerContext

  1. 引入创建的上下文 ClassCreateContext;
  2. 使用 <ClassCreateContext.Consumer> 访问上下文的值和修改值得操作方法;
  3. 在组件 ClassConsumerContext 中展示访问的上下文值 count;
  4. 在组建 ClassConsumerContext 中操作访问的上下文值的方法 updateCount。
import React, { Component } from "react";
import Taro from "@tarojs/taro";
import { View } from "@tarojs/components";
import { ClassCreateContext } from './classCreateContext';

class ClassConsumerContext extends Component {
  constructor(props) {
    super(props);
  }
  state = {  }
  render() { 
    return <ClassCreateContext.Consumer>
      {
        value => (
          <>
            <View>类组件【ClassConsumerContext】</View>
            <View>获取上下文 count: {value.count}</View>
            <View>修改父组件的 count</View>
            <View className='rui-flex-ac'>
              <View 
                onClick={value.updateCount.bind(null, 'add')}
                className='rui-flex-cc rui-fg'>consumer 加</View>
              <View 
                onClick={value.updateCount.bind(null, 'minus')}
                className='rui-flex-cc rui-fg'>consumer 减</View>
            </View>
          </>
        )
      }
    </ClassCreateContext.Consumer>;
  }
}

export default ClassConsumerContext;

8. 结果预览

输入图片说明

2. 方案二:父组件为函数组件访问上下文

9. 父组件为函数组件访问上下文

  1. HookCreateContext 创建上下文;
  2. HookSonContext 函数组件使用 useContext 访问上下文;
  3. ClassSonContext 类组件使用 static contextType 访问上下文;
  4. ClassSonConsumerContext 类组件使用 <XxxContext.Consumer> 访问上下文;
  5. 父组件 count 变量;
  6. 父组件修改 count 的操作函数 updateCount;
  7. 创建上下文并提供值 HookCreateContext.Provider。
import { View, Text, Image } from '@tarojs/components';
import { useState, useEffect } from 'react';
import { HookCreateContext } from './hookCreateContext';
import ClassSonContext from './classSonContext';
import HookSonContext from './HookSonContext';

const HookContext = (props) => {
  let [count, setCount] = useState(0)
  // 修改 count
  function updateCount(type='add'){
    count = {
      'add': () => {
        return ++count
      },
      'minus': () => {
        return --count
      }
    }[type]?.()
    setCount(count)
  }
  return <View>
    <View>父组件 count: {count}</View>
    <View className='rui-flex-ac'>
      <View 
        onClick={updateCount.bind(null, 'add')}
        className='rui-flex-cc rui-fg'>加</View>
      <View 
        onClick={updateCount.bind(null, 'minus')}
        className='rui-flex-cc rui-fg'>减</View>
    </View>
    <HookCreateContext.Provider value={{count, updateCount}}>
      <ClassSonContext/>
      <HookSonContext/>
    </HookCreateContext.Provider>
  </View>
}
export default HookContext;

10. 函数组件创建上下文

hookCreateContext.js

import { createContext } from "react";
// 创建函数组件的上下文
export const HookCreateContext = createContext({});

11. 类组件实现访问上下文和修改上下文值 ClassSonContext

  1. 引入创建的上下文 HookCreateContext;
  2. 使用 static contextType 访问上下文的值和修改值得操作方法;
  3. 在组件 ClassSonContext 中展示访问的上下文值 count;
  4. 在组建 ClassSonContext 中操作访问的上下文值的方法 updateCount。
import React, { Component } from "react";
import Taro from "@tarojs/taro";
import { View } from "@tarojs/components";
import { HookCreateContext } from './hookCreateContext';

class ClassSonContext extends Component {
  static contextType = HookCreateContext;
  constructor(props) {
    super(props);
  }
  state = {  }
  render() { 
    let { count, updateCount } = this.context;
    return <View>
      <View>类组件【ClassSonContext】</View>
      <View>获取上下文 count: {count}</View>
      <View>修改父组件的 count</View>
      <View className='rui-flex-ac'>
        <View 
          onClick={updateCount.bind(null, 'add')}
          className='rui-flex-cc rui-fg'>class 加</View>
        <View 
          onClick={updateCount.bind(null, 'minus')}
          className='rui-flex-cc rui-fg'>class 减</View>
      </View>
    </View>;
  }
}

export default ClassSonContext;

12. 函数组件实现访问上下文和修改上下文值 HookSonContext

  1. 引入创建的上下文 HookCreateContext;
  2. 使用 useContext 访问上下文的值和修改值得操作方法;
  3. 在组件 HookSonContext 中展示访问的上下文值 count;
  4. 在组建 HookSonContext 中操作访问的上下文值的方法 updateCount。
import { View, Text, Image } from '@tarojs/components';
import { useContext } from 'react';
import { HookCreateContext } from './hookCreateContext';

const HookSonContext = (props) => {
  let { count, updateCount } = useContext(HookCreateContext)
  return <View>
    <View>函数组件【HookSonContext】</View>
    <View>获取上下文 count: {count}</View>
    <View>修改父组件的 count</View>
    <View className='rui-flex-ac'>
      <View 
        onClick={updateCount.bind(null, 'add')}
        className='rui-flex-cc rui-fg'>hook 加</View>
      <View 
        onClick={updateCount.bind(null, 'minus')}
        className='rui-flex-cc rui-fg'>hook 减</View>
    </View>
  </View>
}
export default HookSonContext;

13. 结果预览

输入图片说明

14. 总结

  1. 创建上下文使用的是 createContext 方法;
  2. 使用 XxxContext.Provider 给上下文提供值;
  3. 在子组件是函数组件时,可以使用 useContext 访问上下文;
  4. 在子组件是类组件时,可以使用 static contextType 或者 <XxxContext.Consumer> 访问上下文;
  5. 如果是多界面子组件,建议还是传入值操作,访问上下文比较使用一个界面下的所有子组件访问上下文。
  • 30
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rattenking

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值