为什么需要context
你还记得上一次你必须将 props 传递到组件树中的几个组件吗?在 React 中,你经常会遇到这个被称为“props钻孔”的问题:
这么写的问题就是会弄乱中间的每个组件,它们必须往下传递这些props,尽管他们不需要。React Context 为您提供了摆脱这种混乱局面的方法。您可以使用React Context 隐式地将 props 传递给这些组件,而不是通过每个组件向下传递 props 。如果组件需要访问上下文中的信息,它可以按需使用它,因为顶级组件在context中提供此信息。
怎么使用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>
);
};