React 基础巩固(二十一)——Context 和 Spread Attributes
1.使用Spread Attributes
import React, { Component } from "react";
import Home from "./Home";
export class App extends Component {
constructor() {
super();
this.state = {
info: { name: "outman", age: 30 },
};
}
render() {
const { info } = this.state;
return (
<div>
<h2>App</h2>
{/* 利用展开运算符传递对象 */}
<Home {...info} />
</div>
);
}
}
export default App;
import React, { Component } from "react";
export class Home extends Component {
render() {
const { name, age } = this.props;
return (
<div>
<h2>name: {name}</h2>
<h2>age: {age}</h2>
</div>
);
}
}
export default Home;
2.Context的应用
非父子组件数据的共享
- 一些数据需要在多个组件中共享时,在顶层一层层传递下去,对不需要改数据的中间层而言是一种冗余,需要使用 Context。
- Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props
- Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言
Context 的用法
- theme-context.js (封装 context)
import React from "react";
// 创建一个Context
const ThemeContext = React.createContext();
export default ThemeContext;
- Main.jsx(主文件)
import React, { Component } from "react";
import Home from "./Home";
import ThemeContext from "./theme-context";
export class App extends Component {
constructor() {
super();
this.state = {
info: { name: "outman", age: 30 },
};
}
render() {
const { info } = this.state;
return (
<div>
<h2>App</h2>
{/* 通过context中的Provider属性为后代提供数据 */}
<ThemeContext.Provider value={{ color: "red", size: "30" }}>
<Home {...info} />
</ThemeContext.Provider>
</div>
);
}
}
export default App;
- Home.jsx(中间层)
import React, { Component } from "react";
import HomeInfo from "./HomeInfo";
export class Home extends Component {
render() {
return (
<div>
<HomeInfo />
</div>
);
}
}
export default Home;
- HomeInfo.jsx(需要使用 Context 内容的子孙组件)
import React, { Component } from "react";
import ThemeContext from "./theme-context";
export class HomeInfo extends Component {
render() {
// 获取数据并使用
console.log(this.context);
return <div>color: {this.context.color}</div>;
}
}
// 设置组件的contextType为某个context
HomeInfo.contextType = ThemeContext;
export default HomeInfo;
Context 的其他用法
嵌套使用 Context
- 在上例基础上,新增 user-context.js
import React from "react";
// 创建一个Context
const UserContext = React.createContext();
export default UserContext;
- Main.jsx (嵌套使用多个 context)
import React, { Component } from "react";
import Home from "./Home";
import ThemeContext from "./theme-context";
import UserContext from "./user-context";
export class App extends Component {
constructor() {
super();
this.state = {
info: { name: "outman", age: 30 },
};
}
render() {
const { info } = this.state;
return (
<div>
<h2>App</h2>
{/* 嵌套使用 */}
<UserContext.Provider value={{ nickname: "outman", age: "30" }}>
{/* 通过context中的Provider属性为后代提供数据 */}
<ThemeContext.Provider value={{ color: "red", size: "30" }}>
<Home {...info} />
</ThemeContext.Provider>
</UserContext.Provider>
</div>
);
}
}
export default App;
-
Home.jsx
与上例一致 -
HomeInfo.jsx(嵌套使用)
import React, { Component } from "react";
import ThemeContext from "./theme-context";
import UserContext from "./user-context";
export class HomeInfo extends Component {
render() {
// 获取数据并使用
console.log(this.context);
return (
<div>
<h2>color: {this.context.color}</h2>
{/* 嵌套使用 */}
<UserContext.Consumer>
{(value) => {
return <h2>Info User: {value.nickname}</h2>;
}}
</UserContext.Consumer>
</div>
);
}
}
// 设置组件的contextType为某个context
HomeInfo.contextType = ThemeContext;
export default HomeInfo;
Context 相关 API
- React.createContext
- 创建一个需要共享的 Context 对象
- 如果一个组件订阅了 Context,那么这个组件会从离自身最近的那个匹配的 Provider 中读取到当前的 context 值
- defaultValue 是组件在顶层查找过程中没有找到对应的 Provider,则使用的默认值
- Context.Provider
- 每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化
- Provider 接收一个 value 属性,传递给消费组件
- 一个 Provider 可以和多个消费组件有对应关系
- 多个 Provider 可以嵌套使用,里层会覆盖外层数据
- 当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染
- Class.contextType
- 挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext()创建的 Context 对象
- contextType 能使 this.context 来小费最近 Context 上的值
- 可以在任何生命周期中访问到它,包括 render 函数中
- Context.Comsumer
- Comsumer能使函数式组件订阅context
- 需要函数作为子元素(function as child)做法
- 函数接收当前的context值,返回一个React节点