什么是反应上下文 ??
React Context 提供了一种通过组件树传递数据的方法,而无需 props
手动向下传递到每个级别。在 React 中,数据通常作为属性从父组件传递到其子组件。
Context 就像 React 组件子树的全局对象 ?。
Context 解决了什么问题 ??
- 在 React 应用程序中,让父组件将数据长时间传递给子组件,但是当该数据打算由子组件使用多层时出现问题,而不是由该父组件的直接子组件使用。
让我们看下图 ?。
Component A
显然是具有直接子组件 B、C 的主要父组件。这些组件可以从子组件接收参数 component A
并将该数据传递给子组件,但是如果 Component E
需要数据 Component A
并且不需要 Component B
该数据然后将该数据传递给 Component B
变得 多余 。
道具钻探 ,一个术语,用于描述当您通过不需要它的组件将道具向下多层传递到嵌套组件时。
这是 React 上下文的 好处 - 它提供了一种很酷的方式 ? 让 React 应用程序中的每个子组件都可以轻松使用数据。
我们如何使用上下文 ??
据我们所知,React 上下文允许我们在我们的 React 应用程序中需要的任何组件中传递和使用(使用 props
)数据,而无需使用.
使用新的 React Context API 取决于 four
主要步骤:
? 使用 createContext
方法创建上下文。然后,此函数返回一个带有 Provider 和 Consumer 的对象。
import React from 'react';
const AuthContext = React.createContext();
? 接下来,使用 Provider 组件包裹父/主组件。
? 将子组件包装在 Provider 组件中,并使其接受一个名为 value
. 这 value
可以是任何东西!
<AuthContext.Provider value={value}>
<Demo />
</AuthContext.Provider>
? 在组件树中 Provider 下方的任何位置使用 Consumer 组件来获取状态的 子集 。
function Demo() {
return (
<AuthContext.Consumer>
{value => <h1>{value}</h1>}
</AuthContext.Consumer>
);
}
? 让我们看看完整的例子:
import React from 'react';
export const AuthContext = React.createContext();
export default function App() {
return (
<AuthContext.Provider value="Happy">
<Demo />
</AuthContext.Provider>
)
}
function Demo() {
return (
<AuthContext.Consumer>
{value => <h1>{value}</h1>} /* prints happy */
</AuthContext.Consumer>
);
}
在我们的 App 组件之上,我们正在使用创建上下文 React.createContext()
并将结果放入变量中 AuthContext
。
- 几乎在每种情况下,您都希望像我们在这里所做的那样导出它,因为您的组件将在另一个文件中。
请注意,当我们调用 React.createContext() 时,我们可以将初始值传递给我们的 value prop。
- 创建的上下文是一个具有两个属性的对象:
Provider
和Consumer
,它们都是组件。
要记下 Provider 实际所做的事情 ✍️:
➡️ 它拥有一个可以是任何东西的 JavaScript 值:数组、函数或对象。
➡️ 它不会导致其 子级重新渲染 :上下文的提供者的直接子级不会在提供者每次渲染时重新渲染,但消费者会。
此规则仅对由提供者内部 (状态) 引起的重新渲染有效,但如果其父级重新渲染(道具),则提供者的子级也将重新渲染。➡️ 当上下文值发生变化时,所有订阅者都会重新渲染。
- 在我们的 App 组件中,我们使用 AuthContext。具体来说
AuthContext.Provider
,为了将我们的value
向下传递给我们应用程序中的每个组件,我们将我们的 Provider 组件包裹在它周围,在这种情况下,Demo
. - On
AuthContext.Provider
,我们把我们想要传递给整个组件树的值。我们将其设置为等于value
这样做的道具。(这里, 快乐 )。 - 在
Demo
或者我们想要消费上下文中提供的任何地方,我们使用 消费者组件 :AuthContext.Consumer
为了使用我们传递的值,我们使用所谓的 渲染道具模式 。
它只是消费者组件作为prop
. 作为对该函数的回报,我们可以返回并使用那个value
.
使用 useContext 钩子 使用上下文的另一种方式。
? 这是使用 useContext 的相同示例:
import React from 'react';
export const AuthContext = React.createContext();
export default function App() {
return (
<AuthContext.Provider value="Happy">
<Demo />
</AuthContext.Provider>
)
}
function Demo() {
const value = React.useContext(AuthContext);
return <h1>{value}</h1>;
}
useContext 接受上下文类型作为参数,并返回该类型最近的提供者的上下文值。如果没有这样的提供者,那么将返回默认的上下文值。
应用程序的性能会受到影响吗 ??
? 简而言之,如果你的提供者做了很多工作,你的应用程序的性能会 急剧下降 ,例如有一个结合了很多不同值的值,你会有很多同一个提供者的消费者,他们都会重新-使成为。
? 当提供者的包装器由于内部原因(可能是状态)重新渲染时,它的子级不会重新渲染,只有消费者会。这就像您的提供者的价值从提供者传送到消费者,直接忽略了两者之间的一切。
? 因此,拥有多个上下文和提供者是完全可以的。
Redux 与上下文 API 有什么不同?
如您所见,所涉及的概念实际上与 Redux 没有太大区别。
那么上下文是否取代了 redux?
答案是否定的 ?。
Redux 不仅是一种传递 props(传送它们)的方法,它还允许 持久性 ,支持 中间件 ,并且具有更多优势。
我的建议是使用 Redux 进行复杂的全局状态管理,使用 Context 进行道具钻探。
由于这篇文章不是要讨论 redux,所以我会放一些有用的资源来阅读更多关于这个比较的内容 ?。
- 在 StackOverflow 上回答。
- Dan 关于你可能不需要 Redux 的帖子。
在本文中,我们探讨了如何轻松使用 React Context 而不是传递 props 在组件之间共享数据 ?。
根据您的用例,您可能更喜欢使用简单的 props 、React Context 甚至像 Redux 这样的第三方库来在组件之间共享数据。