组件跨层级通信Context,类比Vue中的provider,Inject。
场景:一键换肤,切换地区
1,Context.js
API:
React.createContext
创建一个Context对象,当React渲染一个订阅了这个Context对象的组件,这个租金会从组件树中离自身最近的那个匹配的Provider中读取到当前的Context的值。
Context.Provider
Provider接受一个value属性,传递给消费组件,允许消费组件订阅context的变化。一个Provider可以和多个消费组件有对应关系。多个Provider也可以嵌套使用,里层的会覆盖外层的数据。
当Provider的value值发生变化时,它内部的所有消费组件都会重新渲染。Provider及其内部consumer组件都不受制于shouldComponentUpdate函数,因此当Consumer组件在其祖先组件退出更新的情况下也能更新。
Class.contextType
Context.Consumer
消费者
useContet
import React from "react"; export const ThemeContext = React.createContext({themeColor: "pink"}); export const ThemeProvider = ThemeContext.Provider; //提供者 export const ThemeConsumer = ThemeContext.Consumer; //消费者 export const UserContext = React.createContext(); export const UserProvider = UserContext.Provider; export const UserConsumer = UserContext.Consumer;
2,ContextPage.js
ConsumerPage在<ThemeProvider>的服务区内,必须是Provider的子组件import React, {Component} from "react"; import {ThemeProvider, UserProvider, UserContext} from "../Context"; import ConsumerPage from "./ConsumerPage"; import UseContextPage from "./UseContextPage"; export default class ContextPage extends Component { constructor(props) { super(props); this.state = { theme: { themeColor: "red" }, user: {name: "xiaoming"} }; } render() { const {theme, user} = this.state; return ( <div> <h3>ContextPage</h3> <ThemeProvider value={theme}> <UserProvider value={user}> <ConsumerPage /> <UseContextPage /> </UserProvider> </ThemeProvider> </div> ); } }
3, ConsumerPage.js
接受一个参数返回一个组件
包在<ThemeConsumer>里面,代表是人家的用户
import React, {Component} from "react"; import {ThemeConsumer, UserConsumer} from "../Context"; export default class ConsumerPage extends Component { render() { return ( <div> <h3>ConsumerPage</h3> <ThemeConsumer> {themeContext => ( <div className={themeContext.themeColor}> omg <UserConsumer> {userContext => <Child {...userContext} />} </UserConsumer> </div> )} </ThemeConsumer> </div> ); } } function Child(props) { return <div>{props.name}</div>; }
4,UseContextPage.js
import React, {useContext} from "react"; import {ThemeContext, UserContext} from "../Context"; export default function UseContextPage(props) { const {themeColor} = useContext(ThemeContext); const {name} = useContext(UserContext); return ( <div className="border"> <h3 className={themeColor}>UseContextPage</h3> <p>{name}</p> </div> ); }
总结:
三种使用方式,contextType, Consumer和useContext。
区别:
ContextType,使用简单,必须用在类组件上,只能通过该API订阅单一context.
Consumer,最广泛使用的
useContext,Hook方法,只能用在函数组件当中或者自定义的Hook当中。