一、Context是什么?
Context是React提供的一种跨组件层级共享数据的方式。它解决了React组件之间数据传递的诸多问题。
1.1 基本用法
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
class ThemedButton extends React.Component {
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}
在上述示例中,我们创建一个名为ThemeContext的Context对象并将其默认值设置为“light”。在App组件中提供了ThemeContext的值为“dark”,然后将Toolbar组件渲染到App组件中。Toolbar组件没有直接使用ThemeContext,而是将其传递给子组件ThemedButton,可以通过在ThemedButton类中使用上下文的方式来获取ThemeContext的值,并将其作为Button组件的theme属性传递给它。
1.2. createContext的返回值
React.createContext方法返回一个Context对象。你可以通过Context对象的Provider组件提供一个值,并通过Consumer组件消费该值。例如:
const MyContext = React.createContext(defaultValue);
其中defaultValue在Consumer中没有对应Provider的时候被使用。如果你没有提供defaultValue,而在消费Context的时候没有找到Provider,那么React将会抛出一个错误。
二、Context的原理
2.1. Context简介
在React中,Context允许你在组件之间共享值,而不必显式地传递一个prop。对于许多组件需要访问相同数据源的情况,Context可以帮助你更轻松地传递数据。
2.2. Provider
首先,我们需要Provider来提供需要共享的数据。我们需要使用createContext来创建一个上下文,然后在Provider中传入一个值。这将会创建出一个新的上下文。接下来的步骤中,所有子组件都可以读取这个上下文的值。
示例代码:
const Context = createContext('default value');
class Parent extends React.Component {
render() {
return (
<Context.Provider value="new value">
<Child />
</Context.Provider>
);
}
}
function Child() {
return <Grandchild />;
}
function Grandchild() {
const value = useContext(Context);
return <div>{value}</div>;
}
2.3. Consumer
当数据被包含在上下文中时,后代组件可以使用Consumer获取它。Consumer是一个函数组件,它接收上下文中的值作为参数,并返回表示所呈现内容的React元素。
示例代码:
const Context = createContext('default value');
class Parent extends React.Component {
render() {
return (
<Context.Provider value="new value">
<Child />
</Context.Provider>
);
}
}
function Child() {
return <Grandchild />;
}
function Grandchild() {
return (
<Context.Consumer>
{value => <div>{value}</div>}</Context.Consumer>
);
}
三、实现一个简单的Context
3.1 实现Provider
首先,我们需要在Context对象上定义一个Provider组件。Provider组件需要接收一个value属性,这个属性表示共享的值,它应该被传递给所有后代组件。
示例代码:
const MyContext = React.createContext();
class MyProvider extends React.Component {
render() {
return(
<MyContext.Provider value={{foo: 'bar'}}>
{this.props.children}
</MyContext.Provider>
);
}
}
3.2 实现Consumer
Consumer组件使用高阶组件模式,从Provider组件中获取共享值,然后将值传递给被渲染的组件。这里我们采用render props模式来实现Consumer。
示例代码:
const MyContext = React.createContext();
class MyProvider extends React.Component {
render() {
return(
<MyContext.Provider value={{foo: 'bar'}}>
{this.props.children}
</MyContext.Provider>
);
}
}
class MyConsumer extends React.Component {
render() {
return (
<MyContext.Consumer>
{value => this.props.children(value)}
</MyContext.Consumer>
);
}
}
class App extends React.Component {
render() {
return(
<MyProvider>
<MyConsumer>
{value => <div>The foo value is {value.foo}.</div>}
</MyConsumer>
</MyProvider>
);
}
}
四、结论
本文介绍了React Context的实现原理。Context是React提供的一种跨组件层级共享数据的方式,它解决了React组件之间数据传递的诸多问题。使用createContext方法创建出一个Context对象,然后我们可以在应用中使用Provider和Consumer组件绑定数据。Provider组件提供需要共享的数据,而Consumer组件可以从Provider中获取共享的值。实现了Provider和Consumer组件之后,我们可以在应用中实现跨组件之间的数据传递。