旧版的Context API 在和shouldComponentUpdate
搭配使用时很容易出问题。
在React 16.3版本发布了新的Context API 对使用方法做了大的修改。
首先让我们来看看新版 Context API 都由哪几部分组成:
1.React.createContext
方法用于创建一个 Context 对象。该对象包含Provider
和Consumer
两个属性,分别为两个 React 组件。
2.Provider
组件。用在组件树中更外层的位置。它接受一个名为value
的 prop,其值可以是任何 JavaScript 中的数据类型。
3.Consumer
组件。可以在Provider
组件内部的任何一层使用。它接收一个名为children
值为一个函数的 prop。这个函数的参数是Provider
组件接收的那个value
prop 的值,返回值是一个 React 元素(一段 JSX 代码)。
下面详细解释各部分的含义:
1. 定义全局context对象
import React from 'react'
const GlobalContext = React.createContext(defaultValue)
const {Provider, Consumer} = React.createContext(defaultValue);
export default GlobalContext
可以通过const {Provider, Consumer} = React.createContext(defaultValue) 格式申明Provider 和 Consumer 。
当 React 渲染 context 组件 Consumer 时,它将从组件树的上层中最接近的匹配的 Provider读取当前的 context 值。如果上层的组件树没有一个匹配的 Provider,而此时你需要渲染一个 Consumer 组件,那么你可以用到 defaultValue 。
2. 引入GlobalContext,并使用GlobalContext.Provider(根组件使用,作为生产者)
接收一个 value 属性传递给 Provider 的后代 Consumers。一个 Provider 可以联系到多个 Consumers。Providers 可以被嵌套以覆盖组件树内更深层次的值。
<GlobalContext.Provider
value={{
background: 'green',
color: 'white',
content:this.state.content,
methodA:this.changeStateByChildren
}}
/>
3. 引入GlobalContext并调用context,使用GlobalContext.Consumer(子组件使用,作为消费者)
接收一个函数作为子节点,函数接收当前 context 的值并返回一个 React 节点。传递给函数的 value 将等于组件树中上层 context 的最近的 Provider 的 value 属性。如果 context 没有 Provider ,那么 value 参数将等于被传递给 createContext() 的 defaultValue 。
<GlobalContext.Consumer>
{
context => {
return (
<div>
<h1 style={{background: context.background, color: context.color}}>
{context.content}
</h1>
<Input methodA = {context.methodA} value={context.content}></Input>
</div>
)
}
}
</GlobalContext.Consumer>
注意: Provider
组件使用Object.is
方法判断prop值是否发生改变,当prop的值改变时,其内部组件树中对应的 Consumer
组件会接收到新值并重新渲染。此过程不受 shouldComponentUpdete
方法的影响。
一个使用新版Context API的完整例子:
import React, { Component } from 'react';
import './App.css';
// 第一步,创建 context
const myContext = React.createContext()
// 第二步,创建 Provider Component
class MyProvider extends Component {
state = {
name: "rails365",
age: 27
}
render() {
return (
<myContext.Provider value={{ state: this.state }}>
{ this.props.children }
</myContext.Provider>
)
}
}
const Family = (props) => {
return (
<div>
<h1>Family</h1>
<Person />
</div>
)
}
class Person extends Component {
render() {
return (
<div>
<h1>Person</h1>
<myContext.Consumer>
{ ({ state }) => <p>My age is { state.age }</p> }
</myContext.Consumer>
</div>
);
}
}
class App extends Component {
render() {
return (
<div className="App">
<p>Hello App</p>
<MyProvider>
<Family />
</MyProvider>
</div>
);
}
}
export default App;
参考资料: