Context

Context

如何使用Context

  • Context 设计目的是为了共享那些对于一个组件树而言是 全局 的数据

    ```jsx harmony

// 不使用 Context class App extends React.Component { render() { return ; } }

function Toolbar(props) { return ( ) }

class ThemedButton extends React.Component { render() { return } }

使用Context之前的考虑

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

    • 谨慎使用 因为这会使组件的复用性变差

  • 如果你只是想避免层层传递一些属性,组件组合 component composition 有时是一个比 context 更好的解决方案

```jsx harmony

// ... 渲染出 ...

// ... 渲染出 ...

// ... 渲染出 ...

Api

React.createContext

```jsx harmony

const MyContext = React.createContext(defaultValue);

  • 每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化

  • 一个 Provider 可以和多个消费组件有对应关系 一个 Provider 也可以嵌套使用 里面的会覆盖外层的数据

  • 当 Provider 的值发生变化时,它内部的所有消费组件都会重新渲染

    • Provider 及其内部 consumer 组件都不受制于 shouldComponentUpdate 函数

    • 因此当 consumer 组件在其祖先组件退出更新的情况下也能更新

  • 通过新旧值检测来确定变化,使用了 Object.is 相同的算法

Class.contextType

  • 挂载在 class 上的 contextType 属性会被重新赋值为一个由 React.createContext() 创建的 Context 对象

    • 这能让你使用 this.context 来消费最近的 Context 上的那个值

    • 你可以在任何生命周期函数中访问到它,包括 render 函数中

      ```jsx harmony

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;

  • React 组件也可以订阅到 context 的变更

    • 在函数式组件中完成订阅 context

  • 这个函数接收当前的 context 值,返回一个 React 节点

    • 传递给函数的 value 值等同于往上组件树离这个 context 值最近的 Provider 提供的 value 值

    • 如果没有相应的 Provider,value 参数等同于传递给 createContext() 的 defaultValue

Context.displayName

  • context 对象接受一个名为 displayName 的 property,类型为字符串

  • React DevTools 使用该字符串来确定 context 要显示的内容

示例

动态Context

```jsx harmony

const themes = { light: { foreground: '#000000', background: '#eeeeee' }, dark: { foreground: '#ffffff', background: '#222222' } };

const ThemeContext = React.createContext( themes.light );

class ThemedButton extends React.Component { render() { let props = this.props; let theme = this.context; return ( ) } } ThemedButton.contextType = ThemeContext;

function Toolbar(props) { return ( Change Theme ) }

class App extends React.Component { constructor(props) { super(props); this.state = { theme: themes.light };

}

消费多个Context

  • 为了确保 context 快速进行重渲染,React需要使每一个 consumers 组件的 context 在组件树中成为一个单独的节点

    ```jsx harmony

const ThemeContext = React.createContext('light'); const UserContext = React.createContext({ name: 'Guest', });

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

function Layout() { return ( ) }

class App extends React.Component { render() { const {signedInUser, theme} = this.props;

}

  • 为了避免这种情况,将 value 状态提升到父节点的 state 里

```jsx harmony

class App extends React.Component { constructor(props) { super(props); this.state = { value: {something: 'something'} } }

}

```

最后更新于

这有帮助吗?