React:如何使用useContext

1,360 阅读3分钟

为什么需要context

你还记得上一次你必须将 props 传递到组件树中的几个组件吗?在 React 中,你经常会遇到这个被称为“props钻孔”的问题:

image.png

这么写的问题就是会弄乱中间的每个组件,它们必须往下传递这些props,尽管他们不需要。React Context 为您提供了摆脱这种混乱局面的方法。您可以使用React Context 隐式地将 props 传递给这些组件,而不是通过每个组件向下传递 props 。如果组件需要访问上下文中的信息,它可以按需使用它,因为顶级组件在context中提供此信息。

image.png

怎么使用context

首先,您必须创建 React Context 本身,它可以让您访问 Provider 和 Consumer 组件。当你使用 React的createContext方法创建context时,初始值可以传也可以不传。

// src/ThemeContext.js

import React from 'react';

const ThemeContext = React.createContext(null);

export default ThemeContext;

其次,组件 A 必须为给定的 Provider 组件提供context。在下面这个例子中,它value是一个固定值,但它可以是从组件state(例如fetch data)到props的任何东西。如果该值是可变的,则传递给 Provider 组件的值也是可变的。

// src/ComponentA.js

import React from 'react';
import ThemeContext from './ThemeContext';

const A = () => (
  <ThemeContext.Provider value="green">
    <D />
  </ThemeContext.Provider>
);

组件 A 仅显示组件 D,但不会向它传递任何 props,而是使该值green可用于下面的所有 React 组件。其中一个子组件将是最终使用context的组件 C。

第三,在组件 D 下方的组件 C 中,您可以使用context对象。请注意,组件 A 不需要给组件D传任何props。

// src/ComponentC.js

import React from 'react';
import ThemeContext from './ThemeContext';

const C = () => (
  <ThemeContext.Consumer>
    {value => (
      <p style={{ color: value }}>
        Hello World
      </p>
    )}
  </ThemeContext.Consumer>
);

组件可以通过使用context来派生其样式。Consumer 组件通过使用render prop来消费context。可以想象,按照这种方式,每个需要根据主题进行样式设置的组件现在都可以通过使用 ThemeContext 的 Consumer 组件从Context 中获取必要的信息。您只需要使用 Provider 组件在它们上方的某个地方传递一次值。

什么时候用context

  • 当您的 React 组件层次结构在大小上垂直增长并且您希望能够将 props 传递给子组件而不打扰其中间的组件时。我们在整个 React Context 教程中都使用了这个用例作为示例。
  • 当您想在 React 中使用 React Hooks进行高级状态管理,以便通过 React 应用程序通过 React Context 传递状态和状态更新器功能时。通过 React Context 执行此操作允许您创建共享和全局状态。

**那么接下来就要讲一下useContext的使用了 **

useContext的使用

在前面的示例中,context是静态(或无状态)值。但在大多数用例中,context将用于传递有状态的值。


import React from 'react';

const CurrencyContext = React.createContext(null);
export { CurrencyContext };
//上面三行代码可以抽成一个单独的文件

const App = () => {
  const [currency, setCurrency] = React.useState('€');


  return (
    <CurrencyContext.Provider value={currency}>
      <button type="button" onClick={() => setCurrency('€')}>
        Euro
      </button>
      <button type="button" onClick={() => setCurrency('$')}>
        US Dollar
      </button>

      <Books list={DATA} />
    </CurrencyContext.Provider>
  );
};



const Book = ({ item }) => {
  const currency = React.useContext(CurrencyContext);
  return (
    <li>
      {item.title} - {item.price} {currency}
    </li>
  );
};