Context
Context
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法
在一个典型的 React 应用中,数据是通过 props 属性自上而下进行传递的
但这种做法对于某些类型的属性来说是极其繁琐的
Context 提供了一种在组件之间共享此类值的方法,而不是显式地通过组件树的逐层传递 props
如何使用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'} } }
}
```
最后更新于
这有帮助吗?