react 使用createContext、Consumer 及 useContext 、Class.contextType父子组件共享数据

长话短说:

1、官网

https://react.docschina.org/docs/context.html

2、优点

Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。

3、问题

Context 主要应用场景在于很多不同层级的组件需要访问同样一些的数据。请谨慎使用,因为这会使得组件的复用性变差。

4、函数组件 使用

context.jsx

import { createContext } from "react";

export const themes = {
  light: {
    foreground: '#000000',
    background: '#eeeeee'
  },
  dark: {
    foreground: '#ffffff',
    background: '#aaaaaa'
  }
};

export const ThemeContext = createContext(themes.light)

export const CompAContext = createContext()

index.jsx

import React from 'react';
import { ThemeContext, themes } from './context';
import CompA from './selfComp/CompA';
import CompB from './selfComp/CompB';
import './index.less';

function Context () {
  return (
    <div>
      <ThemeContext.Provider value={themes.dark}>
        组件A:
        <CompA/>
        <br/><br/>
        ------
        <br/><br/>
        组件B:
        <CompB/>
      </ThemeContext.Provider>
    </div>
  )
}

export default Context;

CompA.jsx

import React from 'react';
import { CompAContext } from '../context';
import CompAA from './CompAA';

function CompA () {
  return (
    <div>
      <CompAContext.Provider value={'This is CompA'}>
        <CompAA />
      </CompAContext.Provider>
    </div>
  )
}

export default CompA;

CompAA.jsx

import React,{useContext} from 'react';
import { CompAContext,ThemeContext } from '../context';

function CompAA () {
  const val = useContext(CompAContext)
  const themes = useContext(ThemeContext)
  return (
    // 1、使用useContext
    <>
      <div style={{background: themes.background, color:themes.foreground}}>CompAA</div>
      <div>{'CompAA ------' + val}</div>
    </>

    // 2、CompAContext.Consumer
    // <div>
    //   <CompAContext.Consumer>
    //     {
    //       (val) => (
    //         <ThemeContext.Consumer>
    //           {
    //             themes => (
    //               <>
    //                 <div style={{background: themes.background, color:themes.foreground}}>CompAA</div>
    //                 <div>{'CompAA ------' + val}</div>
    //               </>
    //             )
    //           }
    //         </ThemeContext.Consumer>
    //       )
    //     }
    //   </CompAContext.Consumer>
    // </div>
  )
}

export default CompAA;

CompB.jsx

import React,{useContext} from 'react';
import { ThemeContext } from '../context';

function CompB () {
  const themes = useContext(ThemeContext)
  return (
    // 1、useContext
    <div style={{background: themes.background, color:themes.foreground}}>CompB</div>

    // 2、Consumer
    // <div>
    //   <ThemeContext.Consumer>
    //     {
    //       (themes) => (
    //         <div style={{background: themes.background, color:themes.foreground}}>CompB</div>
    //       )
    //     }
    //   </ThemeContext.Consumer>
    // </div>
  )
}

export default CompB;

总结:

Provider后,子组件中有两种接收值的方法:(详细见上面案例)
 
1、使用 Consumer
 
2、使用 useContext

目录结构

效果

其他: 

1、类组件使用(以 CompB 为例)

class CompB extends React.Component {
  componentDidMount() {
    let themes = this.context;
    /* 在组件挂载完成后,使用 MyContext 组件的值来执行一些有副作用的操作 */
  }
  componentDidUpdate() {
    let themes = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let themes = this.context;
    /* ... */
  }
  render() {
    let themes = this.context;
    /* 基于 MyContext 组件的值进行渲染 */
    <div style={{background: themes.background, color:themes.foreground}}>CompB</div>
  }
}
CompB.contextType = ThemeContext;

 2、如果你正在使用实验性的 public class fields 语法,你可以使用 static 这个类属性来初始化你的 contextType


class CompB extends React.Component {
  static contextType = ThemeContext;
  render() {
    let themes = this.context;
    /* 基于这个值进行渲染工作 */
    <div style={{background: themes.background, color:themes.foreground}}>CompB</div>
  }
}
 
原文地址:https://www.cnblogs.com/-roc/p/15148766.html