React 使用Context提供一个局部的全局作用域共享值

49 min read

Context提供了一个局部的全局作用域,使用Context则无需再手动的逐层传递props

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

Provider 及其内部 consumer 组件都不受制于 shouldComponentUpdate 函数,因此当 consumer 组件在其祖先组件退出更新的情况下也能更新。

组件式

React.createContext提供的ProviderConsumer

  1. React.createContext() 创建状态上下文
import React from "react";
const ActiveKey = React.createContext();

export default ActiveKey;
  1. Consumer组件来订阅Context的变更,需要一个函数作为子元素,函数的第一个形参便是Provider组件提供的value
<ActiveKey.Consumer>
  {activeKey => (
    <div
      className={`bxer-content  ${
      activeKey === item.id ? "bxer-active" : ""
                }`}
      data-id={item.id}
      >
      <span className="bxer-label"></span>
      {item.text}
    </div>
  )}
</ActiveKey.Consumer>
  1. Provider组件接收一个value属性,定义需要向所包裹的组件传递的值
<ActiveKey.Provider value={activeKey}>
  <div
    onClick={event => {
      setActiveKey(event.target.dataset.id, true);
    }}
    className="bxer-box"
    style={{ width: "200px" }}
    >
    {view}
  </div>
</ActiveKey.Provider>

完整的示例如下:

import React from "react";
import ReactDOM from "react-dom";

// Create a Context
const NumberContext = React.createContext();
// It returns an object with 2 values:
// { Provider, Consumer }

function App() {
  // Use the Provider to make a value available to all
  // children and grandchildren
  return (
    <NumberContext.Provider value={42}>
      <div>
        <Display />
      </div>
    </NumberContext.Provider>
  );
}

function Display() {
  // Use the Consumer to grab the value from context
  // Notice this component didn't get any props!
  return (
    <NumberContext.Consumer>
      {value => <div>The answer is {value}.</div>}
    </NumberContext.Consumer>
  );
}

ReactDOM.render(<App />, document.querySelector("#root"));


函数式

使用useContext,接受React.createContext的所有返回,也就是{ Provider, Consumer }, 返回由provide组件传递过来的数值

// import useContext (or we could write React.useContext)
import React, { useContext } from 'react';

// ...

function Display() {
  const value = useContext(NumberContext);
  return <div>The answer is {value}.</div>;
}