組件跨層級通信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
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當中。
react-redux用到Context,react-redux的<Provider />就是通過Context提供一個全局態的store,路由租金react-router通過Context管理路由狀態等。
在React組件開發中,如果用好Context,可以讓你的組件變得強大,而且靈活。