React学习笔记:使用Context进行组件通信(四)

132 阅读3分钟

在一个典型的 React 应用中,数据是通过 props 属性自上而下(由父及子)进行传递的,但此种用法对于某些类型的属性而言是极其繁琐的(例如:地区偏好,UI 主题),这些属性是应用程序中许多组件都需要的。Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。

通俗的讲,contextHook是React提供的比较简易的一个函数,用来实现组件间通信。

如何使用Class里的context

使用creatContext工厂函数创建Context对象

首先引入工厂函数

import {createContext} from React

创建context实例(可以选择是否传入一个default值,若不想要default值可以传入null、undefined)

const ThemeContext = React.createContext( @defaultValue );

使用实例下的Provider方法提供params

子组件需要使用一些方法来接受context

用 static 这个类属性来初始化你的 contextType。如下所示 使用类方法 ReactClass.contextType= 'context实例'

// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。// 为当前的 theme 创建一个 context(“light”为默认值)。
const ThemeContext = React.createContext('light');
class App extends React.Component {
  render() {
    // 使用一个 Provider 来将当前的 theme 传递给以下的组件树。    // 无论多深,任何组件都能读取这个值。    // 在这个例子中,我们将 “dark” 作为当前的值传递下去。    
    return (
       /* @实例下的Proveder方法 */
      <ThemeContext.Provider value="dark">        
          <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// 中间的组件再也不必指明往下传递 theme 了。
function Toolbar() {  
return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // 指定 contextType 读取当前的 theme context。  
  // React 会往上找到最近的 theme Provider,然后使用它的值。  
  // 在这个例子中,当前的 theme 值为 “dark”。  
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;  }
}

使用 Context.Consumer订阅context渲染

如果没有上级provider则读取初始化的context的DefualtValue!!!

<MyContext.Consumer>
  {value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>

使用Context.displayName 指定context对象的名称

这可以让你在使用React提供的Devtools里面查看context对象。

const MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';
<MyContext.Provider> // "MyDisplayName.Provider" 在 DevTools 中
<MyContext.Consumer> // "MyDisplayName.Consumer" 在 DevTools 中

Tips
1. 在组件内部接受的contextValue会寻找离它最近的provider提供的参数
2. 对于模块化的context每个组件调用不受其他组件调用影响。(只要不在同一个provider内)
3. provider里的参数最好最好最好是简单类型,value本质上浅拷贝。
对于多个context可以参考下面使用方式。

function Content() {
  return (
    <ThemeContext.Consumer>      
        {theme => (        
            <UserContext.Consumer>          
                {user => (            
                    <ProfilePage user={user} theme={theme} />          
                )}        
            </UserContext.Consumer>      
         )}    
    </ThemeContext.Consumer>  );
}

如何在函数组件里使用context

基本上一致,但需要在函数组件内声明准确的需要接受的Context实例。
const value = useContext(MyContext);

简单来说,你需要在哪一个函数式组件里接受上级的provider就在那个函数组件内部声明。
而后可以直接在JSX中使用.
同样需要遵守Hook使用规则!!!
这里再强调自己一点,模块化引入的Context只要不在同一个provider互不影响。