ZhengXingchi / ZhengXingchi.github.io

Apache License 2.0
0 stars 0 forks source link

react的Context #92

Open ZhengXingchi opened 4 years ago

ZhengXingchi commented 4 years ago

最初

参考自React的Context的使用方法简介

import React, { Component, createContext } from 'react';

const BatteryContext = createContext();
const OnLineContext = createContext();

//声明一个孙组件
class Leaf extends Component {
  render() {
    return (
      //与Provider类似。Consumer也需要嵌套,顺序不重要。只要Consumer需要声明函数,所以要注意语法。
      <BatteryContext.Consumer>
        {
          battery => (
            <OnLineContext.Consumer>
              {
                online => <h1>Battery : {battery} , Online : {online.toString()}</h1>
              }
            </OnLineContext.Consumer>
          )
        }
      </BatteryContext.Consumer>
    )
  }
}

//声明一个子组件
class Middle extends Component {
  render() {
    return <Leaf />
  }
}

class App extends Component {
  state = {
    battery: 60,
    online: false
  }
  render() {
    const { battery, online } = this.state;
    //接下来声明online的Provider了。如果有多个context变量的话,只需要把Privider嵌套进来即可,顺序不重要。
    return (
      <BatteryContext.Provider value={battery}>
        <OnLineContext.Provider value={online} >
          <button
            type="button"
            onClick={() => this.setState({ battery: battery - 1 })}
          >
            减减
        </button>
          <button
            type="button"
            onClick={() => this.setState({ online: !online })}
          >
            Switch
        </button>
          <Middle />
        </OnLineContext.Provider>
      </BatteryContext.Provider>
    );
  }

}

export default App;

还有一个问题 , 如果Consumer向上找不到对应的Provider怎么办?

其实即使找不到也不会报错,而是显示为空。那怎么设置默认值呢?

那上面的demo举例 ,刚才我们设置的battery为60。如果Consumer向上找不到BatteryContext.Provider的值,我们可以这样设置默认值:const BatteryContext = createContext(30); 这样BatteryContext.Consumer向上找不到值,就会取默认值30。

context不仅仅只是可以传数值,也可以传函数。大家可以试试看。 最后再提示一下大家,不要滥用context,不然会影响组件的独立性。 如果一个组件中只使用一个Context的话,就可以使用contextType代替Consumer。详见进阶

ZhengXingchi commented 4 years ago

进阶

参考自React的contextType的使用方法简介

import React, { Component, createContext } from 'react';

const BatteryContext = createContext();

//声明一个孙组件
class Leaf extends Component {
  static contextType = BatteryContext;
  render() {
    const battery = this.context;
    return<h1>Battery : {battery}</h1>
  }
}

//声明一个子组件
class Middle extends Component {
  render() {
    return <Leaf />
  }
}

class App extends Component {
  state = {
    battery: 60,
  }
  render() {
    const { battery } = this.state;
    return (
      <BatteryContext.Provider value={battery}>
        <button
          type="button"
          onClick={() => this.setState({ battery: battery - 1 })}
        >
          减减
        </button>
        <Middle />
      </BatteryContext.Provider>
    );
  }

}

export default App;

效果和使用Consumer没有什么区别。可见只有一个Context的时候,使用contextType要比使用Consumer简单的多。

ZhengXingchi commented 4 years ago

hooks形式的useContext

import React, { useState ,,useContext, createContext} from 'react';
import './App.css';

// 创建一个 context
const Context = createContext(0)

// 组件一, useContext 写法
function Item3 () {
  const count = useContext(Context);
  return (
    <div>{ count }</div>
  )
}

function App () {
  const [ count, setCount ] = useState(0)
  return (
    <div>
      点击次数: { count } 
      <button onClick={() => { setCount(count + 1)}}>点我</button>
      <Context.Provider value={count}>
        {/* <Item1></Item1>
        <Item2></Item2> */}
        <Item3></Item3>
      </Context.Provider>
    </div>
    )
}

export default App;