React 中 Context 的使用

8 篇文章 0 订阅
5 篇文章 0 订阅

context

Context 提供了一种方式,能够让数据在组件树中传递时不必一级一级的手动传递

一般情况下,数据在组件中,要一级一级的传递,单向数据流,比如Parent组件中的theme值,需要在Item组件中使用,就需要我们从Parent中向下传递, 但当我们有了Context后,我们就不需要一级一级传递了

    Parent(theme=red)
        List(theme=red)
            Item(theme=red)
            
    ThemeContext.Provider value={'red'}
        List
            ThemeContext.Customer  (theme) => { theme }

具体如何使用呢,看下面例子

   
    import React, { createContext } from 'react';

    // 创建Context的唯一方法
    const ThemeContext = createContext()
    
    
    
    class App extends React.Component {
      render () {
        return (
          // 使用 Context.Provider 包裹后续组件,value 指定值 
          <ThemeContext.Provider value={'red'}>
            <Middle></Middle>
          </ThemeContext.Provider>
        )
      }
    }
    
    class Bottom extends React.Component {
      render () {
        return (
          // Context.Consumer Consumer消费者使用Context得值
          // 但子组件不能是其他组件,必须渲染一个函数,函数的参数就是Context得值
          <ThemeContext.Consumer>
            {
              theme => <h1>ThemeContext 的 值为 {theme}</h1>
            }
          </ThemeContext.Consumer>
        )
      }
    }
    
    
    class Middle extends React.Component {
      render () {
        return <Bottom></Bottom>
      }
    }
    
    export default App;

当 Provider 提供的值更改时,Consumer 必须重新渲染

    import React, { createContext } from 'react';
    
    // 创建Context的唯一方法
    const ThemeContext = createContext()
    
    
    
    class App extends React.Component {
      state = {
        theme: 'red'
      }
      render () {
        const { theme } = this.state
        return (
          // 使用 Context.Provider 包裹后续组件,value 指定值 
          <ThemeContext.Provider value={theme}>
            {/* 当Context的Provider值更改时,Consumer 的值必须重新渲染 */}
            <button onClick={() => {this.setState({ theme: 'yellow'})}}>按钮</button>
            <Middle></Middle>
          </ThemeContext.Provider>
        )
      }
    }
    
    class Bottom extends React.Component {
      render () {
        return (
          // Context.Consumer Consumer消费者使用Context得值
          // 但子组件不能是其他组件,必须渲染一个函数,函数的参数就是Context得值
          <ThemeContext.Consumer>
            {
              theme => <h1>ThemeContext 的 值为 {theme}</h1>
            }
          </ThemeContext.Consumer>
        )
      }
    }
    
    
    class Middle extends React.Component {
      render () {
        return <Bottom></Bottom>
      }
    }
    
    export default App;


当出现多个Context的时候,应该如何使用呢

    import React, { createContext } from 'react';

    // 创建Context的唯一方法
    const ThemeContext = createContext()
    const SizeContext = createContext()
    
    
    class App extends React.Component {
      state = {
        theme: 'red',
        size: 'small'
      }
      render () {
        const { theme, size } = this.state
        return (
          // 使用 Context.Provider 包裹后续组件,value 指定值 
          <ThemeContext.Provider value={theme}>
            {/* 当出现多个Context的时候,只需要将Context.Provider 嵌套即可 */}
            <SizeContext.Provider value={size}>
              {/* 当Context的Provider值更改时,Consumer 的值必须重新渲染 */}
              <button onClick={() => {this.setState({ theme: 'yellow', size: 'big'})}}>按钮</button>
              <Middle></Middle>
            </SizeContext.Provider>
          </ThemeContext.Provider>
        )
      }
    }
    
    class Bottom extends React.Component {
      render () {
        return (
          // Context.Consumer Consumer消费者使用Context得值
          // 但子组件不能是其他组件,必须渲染一个函数,函数的参数就是Context得值
          // 当出现 多个Consumer的时候,进行嵌套,每个Consumer 的子组件必须是一个函数,即可
          <ThemeContext.Consumer>
            {
              theme => (
                <SizeContext.Consumer>
                  {
                    size => (<h1>ThemeContext 的 值为 {theme}; SizeContext 的值为 {size}</h1>)
                  }
                </SizeContext.Consumer>
              )
            }
          </ThemeContext.Consumer>
        )
      }
    }
    
    
    class Middle extends React.Component {
      render () {
        return <Bottom></Bottom>
      }
    }
    
    export default App;

假如、Consumer 向上找不到 Provider 的时候,怎么办,react 并不会报错,只不过取不到值而已、这个时候创建 Context 的时候createContext 可以传入默认值,当找不到 Provider 的时候,就会显示默认值

注意:context 类似于全局变量做法,会让组件失去独立性、复用起来更困难,不能滥用、但本身它一定有适合使用的场景,具体看情况使用

contextType

contextType 可以简化 context 的使用,不使用 consumer 也可以共享变量

具体看下面例子

    import React, { createContext } from 'react';
    
    // 创建Context的唯一方法
    const ThemeContext = createContext()
    const SizeContext = createContext()
    
    
    class App extends React.Component {
      state = {
        theme: 'red',
        size: 'small'
      }
      render () {
        const { theme, size } = this.state
        return (
          // 使用 Context.Provider 包裹后续组件,value 指定值 
          <ThemeContext.Provider value={theme}>
            {/* 当出现多个Context的时候,只需要将Context.Provider 嵌套即可 */}
            <SizeContext.Provider value={size}>
              {/* 当Context的Provider值更改时,Consumer 的值必须重新渲染 */}
              <button onClick={() => {this.setState({ theme: 'yellow', size: 'big'})}}>按钮</button>
              <Middle></Middle>
            </SizeContext.Provider>
          </ThemeContext.Provider>
        )
      }
    }
    
    class Bottom extends React.Component {
      // 申明静态变量、contextType 将 context 直接赋值于 contextType
      static contextType = ThemeContext
      
      render () {
        // 在 render 函数中 可以直接 访问 this.context 获取共享变量、这样就可以不使用 consumer
        const theme = this.context
        return (
          // Context.Consumer Consumer消费者使用Context得值
          // 但子组件不能是其他组件,必须渲染一个函数,函数的参数就是Context得值
          // 当出现 多个Consumer的时候,进行嵌套,每个Consumer 的子组件必须是一个函数,即可
          <div>
            <h1>ThemeContext 的 值为 {theme} </h1>
          </div>
        )
      }
    }
    
    
    
    class Middle extends React.Component {
      render () {
        return <Bottom></Bottom>
      }
    }
    
    export default App;

注意:

  • contextType 只能在类组件中使用
    
  • 一个组件如果有多个 consumer , contextType 只对其中一个有效,所以说,contextType 只能有一个

 转载自:https://github.com/landluck/react-go/blob/master/src/context/README.md

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值