您的位置:

React Context 实现原理详解

一、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组件之后,我们可以在应用中实现跨组件之间的数据传递。