What is context in react
In react, context is a method for transferring data between component trees without manually adding props for each layer of components; context provides a way to share specified values between components, and There is no need to explicitly pass props through the component tree.
The operating environment of this tutorial: Windows 10 system, react17.0.1 version, Dell G3 computer.
What is context in react
Context provides a method to transfer data between component trees without manually adding props to each layer of components. In a typical React application, data is passed from top to bottom (from parent to child) through props, but this approach is extremely cumbersome for certain types of properties (e.g. locale preferences, UI theme), these properties are required by many components in the application. Context provides a way to share such values between components without having to explicitly pass props through each level of the component tree.
Context When to use?
Context is designed to share data that is "global" to a component tree, such as the currently authenticated user, theme, or preferred language. For example, in the following code, we manually adjust the style of a button component through a "theme" attribute
class App extends React.Component { render() { return <Toolbar theme="dark" />; } } function Toolbar(props) { // Toolbar 组件接受一个额外的“theme”属性,然后传递给 ThemedButton 组件。 // 如果应用中每一个单独的按钮都需要知道 theme 的值,这会是件很麻烦的事, // 因为必须将这个值层层传递所有组件。 return ( <p> <ThemedButton theme={props.theme} /> </p> ); } class ThemedButton extends React.Component { render() { return <Button theme={this.props.theme} />; } } // 通过props传递:App -> Toolbar -> ThemedButton // 如果嵌套很深,那么需要逐层传递props,即使中间不需要该props,显得很繁琐
Using context, we can avoid passing props through intermediate elements
// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。 // 为当前的 theme 创建一个 context("light"为默认值)。 const ThemeContext = React.createContext('light'); class App extends React.Component { render() { // 使用一个 Provider 来将当前的 theme 传递给以下的组件树。 // 无论多深,任何组件都能读取这个值。 // 在这个例子中,我们将 “dark” 作为当前的值传递下去。 return ( <ThemeContext.Provider value="dark"> <Toolbar /> </ThemeContext.Provider> ); } } // 中间的组件再也不必指明往下传递 theme 了。 function Toolbar() { return ( <p> <ThemedButton /> </p> ); } class ThemedButton extends React.Component { // 指定 contextType 读取当前的 theme context。 // React 会往上找到最近的 theme Provider,然后使用它的值。 // 在这个例子中,当前的 theme 值为 “dark”。 static contextType = ThemeContext; render() { return <Button theme={this.context} />; } } // 也可以使用 ThemedButto.contextType = ThemeContext;
API Introduction
React.createContext
const MyContext = React.createContext(defaultValue);
Create a Context object. When React renders a component subscribed to this Context object, the component will read the current context value from the matching Provider
closest to itself in the component tree.
Only when there is no matching Provider in the tree where the component is located, its defaultValue
parameter will take effect. This helps in testing components without wrapping them with a Provider. Note: When undefined
is passed to Provider's value, the defaultValue
of the consuming component will not take effect.
Context.Provider
<MyContext.Provider value={/* 某个值 */}>
Each Context object returns a Provider React component, which allows consuming components to subscribe to context changes.
Provider receives a value
attribute and passes it to the consuming component. A Provider can have a corresponding relationship with multiple consumer components. Multiple Providers can also be used nested, and the inner layer will overwrite the outer layer's data.
When the Provider's value
value changes, all consuming components inside it will be re-rendered. Neither the Provider nor its internal consumer component is subject to the shouldComponentUpdate
function, so the consumer component can be updated even if its ancestor component exits update.
Class.contextType
The contextType
attribute mounted on the class will be reassigned to a Context created by React.createContext() object. This allows you to use this.context
to consume the value on the most recent Context. You can access it in any life cycle, including in the render function
import MyContext from './MyContext'; class MyClass extends React.Component { componentDidMount() { let value = this.context; /* 在组件挂载完成后,使用 MyContext 组件的值来执行一些有副作用的操作 */ } componentDidUpdate() { let value = this.context; /* ... */ } componentWillUnmount() { let value = this.context; /* ... */ } render() { let value = this.context; /* 基于 MyContext 组件的值进行渲染 */ } // 或者如上边例子一样使用 static contextType = MyContext; } MyClass.contextType = MyContext;
Context.Consumer
import MyContext from './MyContext'; function ToolList() { return ( <MyContext.Consumer {value => /* 基于 context 值进行渲染*/} </MyContext.Consumer> ) }
Here, React components can also subscribe to context changes. This allows you to subscribe to context in functional components.
This requires function as a child. This function receives the current context value and returns a React node. The value
value passed to the function is equivalent to the value
value provided by the Provider closest to this context up the component tree. If there is no corresponding Provider, the value
parameter is equivalent to the defaultValue
passed to createContext()
.
Context.displayName
The context object accepts a property named displayName
, which is of type string. React DevTools uses this string to determine what context to display.
The following component will be displayed as MyDisplayName in DevTools
const MyContext = React.createContext(/* some value */); MyContext.displayName = 'MyDisplayName'; <MyContext.Provider> // "MyDisplayName.Provider" 在 DevTools 中 <MyContext.Consumer> // "MyDisplayName.Consumer" 在 DevTools 中
Example
Dynamic Context
For the theme example above, use dynamic values for more complex usage
theme-context.js
export const themes = { light: { foreground: '#000000', background: '#eeeeee', }, dark: { foreground: '#ffffff', background: '#222222', }, }; export const ThemeContext = React.createContext(themes.dark); // 该处为默认值
themed-button.js
import { ThemeContext } from './theme-context'; class ThemedButton extends React.Component { render() { let props = this.props; // 获取到ThemeContext中的默认值 let theme = this.context; return ( <button {...props} style={{backgroundColor: theme.background}} /> ); } // static contextType = ThemeContext; } ThemedButton.contextType = ThemeContext; export default ThemedButton;
app.js
import { ThemeContext, themes } from './theme-context'; import ThemedButton from './themed-button'; // 一个使用 ThemedButton 的中间组件 function Toolbar(props) { return ( <ThemedButton onClick={props.changeTheme}> Change Theme </ThemedButton> ); } class App extends React.Component { constructor(props) { super(props); this.state = { theme: themes.light, }; this.toggleTheme = () => { this.setState(state => ({ theme: state.theme === themes.dark ? themes.light : themes.dark, })); }; } render() { // 在 ThemeProvider 内部的 ThemedButton 按钮组件使用 state 中的 theme 值, // 而外部的组件使用默认的 theme 值 return ( <Page> <ThemeContext.Provider value={this.state.theme}> <Toolbar changeTheme={this.toggleTheme} /> </ThemeContext.Provider> <Section> <ThemedButton /> </Section> </Page> ); } } ReactDOM.render(<App />, document.root); // 使用ThemeContext.Provider包裹的组件,可以消费到ThemeContext中的value // 即Toolbar、ThemedButton中都可以使用this.context来获取到value // 注意观察,更新state的方法是通过props向下传递,由子孙组件触发更新,下面会讲到通过context的方式传递更新函数
在嵌套组件中更新 Context
在上面的例子中,我们通过 props 的方式向下传递一个更新函数,从而改变 App 中 themes 的值。我们知道,从一个在组件树中嵌套很深的组件中更新 context 是很有必要的。在这种场景下,你可以通过 context 传递一个函数,使得 consumers 组件更新 context
theme-context.js
// 确保传递给 createContext 的默认值数据结构是调用的组件(consumers)所能匹配的! export const ThemeContext = React.createContext({ theme: themes.dark, toggleTheme: () => {}, // 定义更新主题的方法,向下传递 });
theme-toggler-button.js
import { ThemeContext } from './theme-context'; function ThemeTogglerButton() { // Theme Toggler 按钮不仅仅只获取 theme 值,它也从 context 中获取到一个 toggleTheme 函数(下面app.js部分) return ( <ThemeContext.Consumer> {({theme, toggleTheme}) => ( <button onClick={toggleTheme} style={{backgroundColor: theme.background}}> Toggle Theme </button> )} </ThemeContext.Consumer> ); } export default ThemeTogglerButton;
app.js
import { ThemeContext, themes } from './theme-context'; import ThemeTogglerButton from './theme-toggler-button'; class App extends React.Component { constructor(props) { super(props); this.toggleTheme = () => { this.setState(state => ({ theme: state.theme === themes.dark ? themes.light : themes.dark, })); }; // State 也包含了更新函数,因此它会被传递进 context provider。 this.state = { theme: themes.light, toggleTheme: this.toggleTheme, // 定义更新函数,通过context方式向下传递 }; } render() { // 整个 state 都被传递进 provider return ( <ThemeContext.Provider value={this.state}> <Content /> </ThemeContext.Provider> ); } } function Content() { return ( <p> <ThemeTogglerButton /> </p> ); } ReactDOM.render(<App />, document.root);
消费多个 Context
为了确保 context 快速进行重渲染,React 需要使每一个 consumers 组件的 context 在组件树中成为一个单独的节点
// Theme context,默认的 theme 是 "light" 值 const ThemeContext = React.createContext('light'); // 用户登录 context const UserContext = React.createContext({ name: 'Guest', }); class App extends React.Component { render() { const { signedInUser, theme } = this.props; // 提供初始 context 值的 App 组件 return ( <ThemeContext.Provider value={theme}> <UserContext.Provider value={signedInUser}> <Layout /> </UserContext.Provider> </ThemeContext.Provider> ); } } function Layout() { return ( <p> <Sidebar /> <Content /> </p> ); } // 一个组件可能会消费多个 context function Content() { return ( <ThemeContext.Consumer> {theme => ( <UserContext.Consumer> {user => ( <ProfilePage user={user} theme={theme} /> )} </UserContext.Consumer> )} </ThemeContext.Consumer> ); }
如果两个或者更多的 context 值经常被一起使用,那你可能要考虑一下另外创建你自己的渲染组件,以提供这些值。
注意事项
因为 context 会使用参考标识(reference identity)来决定何时进行渲染,这里可能会有一些陷阱,当 provider 的父组件进行重渲染时,可能会在 consumers 组件中触发意外的渲染。举个例子,当每一次 Provider 重渲染时,以下的代码会重渲染所有下面的 consumers 组件,因为 value
属性总是被赋值为新的对象
class App extends React.Component { render() { return ( <MyContext.Provider value={{something: 'something'}}> <Toolbar /> </MyContext.Provider> ); } }
为了防止这种情况,将 value 状态提升到父节点的 state 里
class App extends React.Component { constructor(props) { super(props); // 多次渲染,state 会被保留,当value不变时,下面的 consumers 组件不会重新渲染 this.state = { value: {something: 'something'}, }; } render() { return ( <Provider value={this.state.value}> <Toolbar /> </Provider> ); } }
【相关推荐:javascript视频教程、web前端】
The above is the detailed content of What is context in react. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



How to build a real-time chat application using React and WebSocket Introduction: With the rapid development of the Internet, real-time communication has attracted more and more attention. Live chat apps have become an integral part of modern social and work life. This article will introduce how to build a simple real-time chat application using React and WebSocket, and provide specific code examples. 1. Technical preparation Before starting to build a real-time chat application, we need to prepare the following technologies and tools: React: one for building

React front-end and back-end separation guide: How to achieve front-end and back-end decoupling and independent deployment, specific code examples are required In today's web development environment, front-end and back-end separation has become a trend. By separating front-end and back-end code, development work can be made more flexible, efficient, and facilitate team collaboration. This article will introduce how to use React to achieve front-end and back-end separation, thereby achieving the goals of decoupling and independent deployment. First, we need to understand what front-end and back-end separation is. In the traditional web development model, the front-end and back-end are coupled

How to use React and Flask to build simple and easy-to-use web applications Introduction: With the development of the Internet, the needs of web applications are becoming more and more diverse and complex. In order to meet user requirements for ease of use and performance, it is becoming increasingly important to use modern technology stacks to build network applications. React and Flask are two very popular frameworks for front-end and back-end development, and they work well together to build simple and easy-to-use web applications. This article will detail how to leverage React and Flask

How to build a reliable messaging application with React and RabbitMQ Introduction: Modern applications need to support reliable messaging to achieve features such as real-time updates and data synchronization. React is a popular JavaScript library for building user interfaces, while RabbitMQ is a reliable messaging middleware. This article will introduce how to combine React and RabbitMQ to build a reliable messaging application, and provide specific code examples. RabbitMQ overview:

React code debugging guide: How to quickly locate and resolve front-end bugs Introduction: When developing React applications, you often encounter a variety of bugs that may crash the application or cause incorrect behavior. Therefore, mastering debugging skills is an essential ability for every React developer. This article will introduce some practical techniques for locating and solving front-end bugs, and provide specific code examples to help readers quickly locate and solve bugs in React applications. 1. Selection of debugging tools: In Re

ReactRouter User Guide: How to Implement Front-End Routing Control With the popularity of single-page applications, front-end routing has become an important part that cannot be ignored. As the most popular routing library in the React ecosystem, ReactRouter provides rich functions and easy-to-use APIs, making the implementation of front-end routing very simple and flexible. This article will introduce how to use ReactRouter and provide some specific code examples. To install ReactRouter first, we need

How to use React and Google BigQuery to build fast data analysis applications Introduction: In today's era of information explosion, data analysis has become an indispensable link in various industries. Among them, building fast and efficient data analysis applications has become the goal pursued by many companies and individuals. This article will introduce how to use React and Google BigQuery to build a fast data analysis application, and provide detailed code examples. 1. Overview React is a tool for building

How to use React and Docker to package and deploy front-end applications. Packaging and deployment of front-end applications is a very important part of project development. With the rapid development of modern front-end frameworks, React has become the first choice for many front-end developers. As a containerization solution, Docker can greatly simplify the application deployment process. This article will introduce how to use React and Docker to package and deploy front-end applications, and provide specific code examples. 1. Preparation Before starting, we need to install
