React-context

161 阅读2分钟

React16.x之前——基本用法

import React, { Component } from 'react';
import './App.css';
import PropTypes from 'prop-types';

const Topic = (props) => {
  return (
    <div>
      <Comment />
    </div>
  )
}

//使用context的组件
const Comment = (props, context) => {
  return (
    <div>{ context.color }</div>
  )
}
Comment.contextTypes = {
  color: PropTypes.string
}

//父组件
class App extends Component {
  getChildContext() {
    return { color: "red" };
  }
  render() {
    return (
      <div className="App">
        <Topic />
      </div>
    );
  }
}
App.childContextTypes = {
  color: PropTypes.string
}
export default App;

React16.x之后——基本用法

// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的 theme 创建一个 context(“light”为默认值)。
const ThemeContext = React.createContext('light');
ThemeContext.displayName = '主题颜色'; //React DevTools 使用该字符串来确定 context 要显示的内容。

class App extends React.Component {
  state = {
      theme:'dark',
  }
  render() {
    // 使用一个 Provider 来将当前的 theme 传递给以下的组件树。    
    // 无论多深,任何组件都能读取这个值。    
    // 在这个例子中,我们使用组件状态theme的值 “dark” 作为当前的值传递下去。
    const { theme } = this.state;
    return (
      <ThemeContext.Provider value={theme}>        
          <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

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

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

//函数式组件使用
<ThemeContext.Consumer>
  {value => ()/* 基于 context 值进行渲染*/}
</ThemeContext.Consumer>

Context 主要应用场景在于很多不同层级的组件需要访问同样一些的数据。

请谨慎使用,因为这会使得组件的复用性变差。

Class.contextType

挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。此属性能让你使用 this.context 来读取最近 Context 上的那个值。

class MyClass extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* 在组件挂载完成后,使用 MyContext 组件的值来执行一些有副作用的操作 */
  }
  componentDidUpdate() {
    let value = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let value = this.context;
    /* ... */
  }
  render() {
    let value = this.context;
    /* 基于 MyContext 组件的值进行渲染 */
  }
}
MyClass.contextType = MyContext;

多个Context

// Theme context,默认的 theme 是 “light” 值
const ThemeContext = React.createContext('light');

// 用户登录 context
const UserContext = React.createContext({
  name: 'Guest',
});

class App extends React.Component {
    render() {
        const {signedInUser, theme} = this.props;
        // 提供初始 context 值的 App 组件
        return (
            <ThemeContext.Provider value={theme}>        
                <UserContext.Provider value={signedInUser}>          
                    <Layout />
                </UserContext.Provider>     
            </ThemeContext.Provider>    
        );
    }
}

function Layout() {
  return (
    <div>
      <Sidebar />
      <Content />
    </div>
  );
}

// 一个组件可能会消费多个 context
function Content() {
  return (
    <ThemeContext.Consumer>      
        {theme => (        
            <UserContext.Consumer>          
                {user => (            
                    <ProfilePage user={user} theme={theme} />         
                )}        
            </UserContext.Consumer>      
        )}    
    </ThemeContext.Consumer>  );
}