React-Context理解

React-Context

类似广播功能

可以无视props进行值传递,多用于共用值:

例如:

import React from 'react';
const CommonUse = React.createContext(
  "公用参数"
);
export default class UseContext extends React.Component{
    constructor(props){
      super(props);
    }
    render(){
      return (
        <div>
          Context的使用
          <CommonUse.Provider value="everyone to use">
            <ContextChild />
            <ContextChildTwo />
          </CommonUse.Provider>
        </div>
      )
    }
}

class ContextChild extends React.Component{ 
  render(){
    return (
      <div>子组件 {this.context}</div>
    )
  }
}
ContextChild.contextType = CommonUse; 

class ContextChildTwo extends React.Component{
  render(){
    return (
      <CommonUse.Consumer>
        {value => (
          <div>
            {this.context['name']}
            <ContextChildTwoChild />
          </div>
        )}
      </CommonUse.Consumer>
    )
  }
}
class ContextChildTwoChild extends React.Component{ 
  static contextType = CommonUse;
  render(){
    return(
        <div>我也在用 我是2的子组件 {this.context} </div>
    )
  }
}

定义完Context后需要将用此值的组件放在

<MyContext.Provider value="要传递的值"> </MyContext.Provider>

标签中。


注:使用this.context的时候必须经过contextType的挂载,官方提供三种方法,第三种方法可供函数组件使用

//1. 将contextType挂载到类上:
class ContextChildTwo extends React.Component{ 
  render(){
    return (
      <div>{this.context}</div>
    )
  }
}
ContextChildTwo.contextType = CommonUse; 
//2.使用实验性语法static
class ContextChildTwo extends React.Component{
  static contextType = CommonUse;
  render(){
    return (
      <div>
        	{this.context} 
      </div>
    )
  }
}
//3.使用Context.Consumer(订阅context更新)
class ContextChildTwo extends React.Component{
  render(){
    return (
      <CommonUse.Consumer>
        {value => (
          <div>
            {this.context['name']} 
          </div>
        )}
      </CommonUse.Consumer>
    )
  }
}

如果要传递对象的时候要这么写,否则可能出现问题

import React from 'react';
const CommonUse = React.createContext(
  "公用参数"
);
export default class UseContext extends React.Component{
    constructor(props){
      super(props);
      // ********** 
      this.state = {
        contextValue :{
          name : 'Oh'
        }
      }
    }
    render(){
      return (
        <div>
          Context的使用
          <CommonUse.Provider value={this.state.contextValue}>
            <ContextChild />
          </CommonUse.Provider>
        </div>
      )
    }
}

class ContextChild extends React.Component{
  render(){
    return (
      <div>子组件 {this.context['name']}</div>
    )
  }
}
ContextChild.contextType = CommonUse;

初始如果想将context默认值定义为对象则这么写:

const contextObj = {
    
    
    name:"Tom"
}
const NameContext = React.createContext(contextObj);

动态修改context

const ActiveObjectValue = {
  name:"Tom",
  othername:"Jack"
}
const ActiveContext = React.createContext(ActiveObjectValue);
class Active extends React.Component{
  constructor(props){
    super(props);
    this.changeName = ()=>{ 
      this.setState(state=>({
        name:state.name == ActiveObjectValue['name'] ? ActiveObjectValue['othername'] : ActiveObjectValue['name']
      }))
    }
    this.state = {
      name:"Jack"
    }
  }
  render(){
    return (
      <ActiveContext.Provider value={this.state.name}>
          <ActiveChild changeName={this.changeName}/>
      </ActiveContext.Provider>
    )
  }
}
class ActiveChild extends React.Component{
  render(){
    return (
      <div>
          <button onClick={this.props.changeName}>{this.context}</button>
      </div>
    )
  }
}
ActiveChild.contextType = ActiveContext;

在嵌套组件中更新Context

写一个例子,通过点击按钮改变姓名:

const NameObject = {
  name : "Tom",
  othername:"Jack"
}
const ContextObject = {
  name:NameObject['name'],
  changeName:()=>{}
}
const UseContextObject = React.createContext(ContextObject);
//父组件
class Parent extends React.Component{
  constructor(props){
    super(props);
    this.changeName = ()=>{
      this.setState(state=>({
        name:state['name'] == NameObject['name'] ? NameObject['othername'] : NameObject['name']
      }))
    }
    this.state = {
      name:NameObject['name'],
      changeName:this.changeName
    }
  }
  render(){
    return (
      <div>
        <UseContextObject.Provider value={this.state}>
          <Content />
        </UseContextObject.Provider>
      </div>
    )
  }
}
//嵌套
class Content extends React.Component{
  render(){
    return (
      <div><Child/></div>
    )
  }
}
//末端子组件
class Child extends React.Component{
  render(){
    return(
      <UseContextObject.Consumer>
        {
          ({name,changeName})=>(
            <div>
              <button onClick={changeName}>{name}</button>
            </div>
          )
        }
      </UseContextObject.Consumer>
    )
  }
} 

首先为context定义初始值和修改姓名的方法

然后在在父组件构造函数中的state中定义姓名和更改姓名的方法,并将state全部传给最末端子组件的context

然后在子组件中使用.Consumer来实现点击切换姓名。(Consumer可以订阅context变更)


两个Context嵌套使用

使用Context.Consumer标签:

import React  from 'react';
const CommonUse = React.createContext(
  "公用参数"
);
const CommonUseTwo = React.createContext('default');
export default class UseContext extends React.Component{
    constructor(props){
      super(props);
      this.state = {
        contextValue :{
          name : 'Oh'
        }
      }
    }
    render(){
      return (
        <div>
          Context的使用
          <CommonUseTwo.Provider value="嵌套使用">
            <CommonUse.Provider value={this.state.contextValue}>
              <ContextChild /> 
            </CommonUse.Provider>
          </CommonUseTwo.Provider>
        </div>
      )
    }
}

class ContextChild extends React.Component{
  render(){
    return (
      <div>
        <CommonUse.Consumer>
          {value =>(
            <CommonUseTwo.Consumer>
              {valueTwo => (
                <div>双值嵌套 + {value['name']} + {valueTwo}</div>
              )}
            </CommonUseTwo.Consumer>
          )}
        </CommonUse.Consumer>
      </div>
    )
  }
}

子组件中使用这种方式:

<CommonUse.Consumer>
    {value =>(
     <CommonUseTwo.Consumer>
     	{valueTwo => (
     		<div>双值嵌套 + {value['name']} + {valueTwo}</div>
		)}
     </CommonUseTwo.Consumer>
	)}
</CommonUse.Consumer>

将所需的两个值分别嵌套,内层值在外层值的回调中使用。


组合组件减少props传值次数

比如这样一种情况的出现:

import React from 'react';
function Top(props){
  return <Center/>
}
function Center(props){
  return <CenterTwo/>
}
function CenterTwo(props){
  return <Bottom/>
}
function Bottom(props){
  return <div>{ props.name }{ prps.age }</div>
}
export default Top;

原先传递数据的方式:

import React from 'react';
function Top(props){
  return <Center name="Tom" age="20"/>
}
function Center(props){
  return <CenterTwo name={props.name} age={props.age} />
}
function CenterTwo(props){
  return <Bottom name={props.name} age={props.age} />
}
function Bottom(props){
  return <div>{ props.name }{ prps.age }</div>
}
export default Top;

可以看到只有最底下的组件需要这几个值,如果嵌套层数过多会导致中间组件获取无用参数过多,显得过于繁杂。


下面来使用组合方式减少传值数量:

import React from 'react';
function Top(props){
  var name = "tom";
  var age = "20";
  const Bottom = (
     <div>{name}{age}</div>
  )
  return <Center useBottom={Bottom}/>
}
function Center(props){
  return <CenterTwo useBottom={props.useBottom}/>
}
function CenterTwo(props){
  var useBottom = props.useBottom;
  return (
     <div>
       {useBottom}
     </div>
  )
} 
export default Top;

因为中间的组件不需要这两个值,所以将值直接交给顶层处理,可减少大量无用的值传递。

Guess you like

Origin blog.csdn.net/weixin_41564885/article/details/108502839