這篇文章給大家分享的是有關(guān)Context-React如何跨組件訪問(wèn)數(shù)據(jù)的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。
成都網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專注于網(wǎng)頁(yè)設(shè)計(jì)、成都網(wǎng)站建設(shè)、微信開(kāi)發(fā)、小程序設(shè)計(jì)、集團(tuán)成都定制網(wǎng)站等服務(wù)項(xiàng)目。核心團(tuán)隊(duì)均擁有互聯(lián)網(wǎng)行業(yè)多年經(jīng)驗(yàn),服務(wù)眾多知名企業(yè)客戶;涵蓋的客戶類(lèi)型包括:宴會(huì)酒店設(shè)計(jì)等眾多領(lǐng)域,積累了大量豐富的經(jīng)驗(yàn),同時(shí)也獲得了客戶的一致贊揚(yáng)!Context提供了一種跨組件訪問(wèn)數(shù)據(jù)的方法。它無(wú)需在組件樹(shù)間逐層傳遞屬性,也可以方便的訪問(wèn)其他組件的數(shù)據(jù)
在經(jīng)典的React應(yīng)用中,數(shù)據(jù)是父組件通過(guò)props向子組件傳遞的。但是在某些特定場(chǎng)合,有些數(shù)據(jù)需要在各個(gè)組件之間共享。Context為我們提供一種組件之間共享數(shù)據(jù)的方式,可以避免數(shù)據(jù)在組件樹(shù)上逐層傳遞
使用Context的場(chǎng)合
Context可以在組件樹(shù)的組件之間共享“全局”數(shù)據(jù)。例如:登陸的用戶信息,用戶選擇的主題、語(yǔ)言等等。下面的例子中,我們“手動(dòng)”自上而下傳遞theme屬性,用來(lái)設(shè)定Button的樣式。
class App extends React.Component {
render() {
return
}
}
function Toolbar(props) {
// The Toolbar component must take an extra "theme" prop
// and pass it to the ThemedButton. This can become painful
// if every single button in the app needs to know the theme
// because it would have to be passed through all components.
return (
// A component in the middle doesn't have to
// pass the theme down explicitly anymore.
function Toolbar(props) {
return (
class ThemedButton extends React.Component {
// Assign a contextType to read the current theme context.
// React will find the closest theme Provider above and use its value.
// In this example, the current theme is "dark".
static contextType = ThemeContext;
render() {
return ;
}
}
有時(shí)候,有些數(shù)據(jù)需要被很多組件訪問(wèn),而且這些組件在組件樹(shù)的不同層上。Context可以使我們以“廣播”的形式,在各個(gè)組件中共享數(shù)據(jù)的改變
Context相關(guān)API
React.createContext
const MyContext = React.createContext(defaultValue);復(fù)制代碼
創(chuàng)建一個(gè)新的Context對(duì)象。當(dāng)React渲染一個(gè)組件,且該組件注冊(cè)了Context時(shí),它將讀取父組件中,距離該組件最近的Provider組件的Context值
defaultValue只有在“Consumer”組件找不到Provider組件時(shí),才會(huì)被使用。
Context.Provider
每個(gè)Context對(duì)象都攜帶一個(gè)名叫Provider的React組件。Provider可以使得“Consumer”組件監(jiān)聽(tīng)context的變更
通過(guò)向Provider的后代Consumer組件傳遞value的prop,一個(gè)Provider可以與多個(gè)Consumer組件建立聯(lián)系。
所有的后代Consumer組件在Provider的value屬性更新后,都會(huì)被重新渲染。這個(gè)更新從Provider到其后代Consumer組件之間傳播,但是并不會(huì)觸發(fā)shouldComponentUpdate方法。所以即使Consumer組件的祖先組件沒(méi)有更新,Consumer組件也會(huì)更新
Context使用與Object.is相同的算法來(lái)對(duì)比value的新、舊值,以判定其value是否被更新了
注意
當(dāng)向value傳遞對(duì)象時(shí),這種判定value是否改變的方式可能會(huì)引起問(wèn)題。
Class.contextType
class MyClass extends React.Component {
componentDidMount() {
let value = this.context;
/ perform a side-effect at mount using the value of MyContext/
}
componentDidUpdate() {
let value = this.context;
/ .../
}
componentWillUnmount() {
let value = this.context;
/ .../
}
render() {
let value = this.context;
/ render something based on the value of MyContext/
}
}
MyClass.contextType = MyContext;
為class的contextTpe屬性賦值一個(gè)Context對(duì)象后,我們可以通過(guò)this.context在組件的各個(gè)聲明周期函數(shù)中獲取到當(dāng)前的Context對(duì)象的方法
注意:
通過(guò)這種方式,每個(gè)組件只能注冊(cè)一個(gè)context對(duì)象。如果需要讀取多個(gè)context的value值
如果編碼中使用了ES實(shí)驗(yàn)中的語(yǔ)法,那么可以使用類(lèi)的靜態(tài)(static)成員來(lái)初始化contextTYpe.代碼如下:
class MyClass extends React.Component {
static contextType = MyContext;
render() {
let value = this.context;
/ render something based on the value/
}
}
Context.Consumer
{value => / render something based on the context value/}
Consumer是一個(gè)監(jiān)聽(tīng)context變化的React組件。它使得我們可以在一個(gè)函數(shù)組件中,監(jiān)聽(tīng)contxt的改變。
Consumer組件要求其子元素為一個(gè)函數(shù)。該函數(shù)的參數(shù)接收當(dāng)前的context的value值,要求返回一個(gè)React節(jié)點(diǎn)(node) 傳遞給該函數(shù)的參數(shù)value等于距離此Consumner最近的外層Provider組件的context值。如果沒(méi)有外層的Provider組件,則等于調(diào)用createContext()時(shí)傳遞的參數(shù)值(context的默認(rèn)值)。
注意
更多關(guān)于“子元素為一個(gè)函數(shù)”的信息
栗子
在嵌套組件中更新Context
開(kāi)發(fā)中,我們經(jīng)常需要在某些嵌套結(jié)構(gòu)很深的組件上更新context的value值。此時(shí),我們可以向下傳遞一個(gè)函數(shù),用它來(lái)更新context的value。代碼如下:
theme-context.js
// Make sure the shape of the default value passed to// createContext matches the shape that the consumers expect!export const ThemeContext = React.createContext({
theme: themes.dark,
toggleTheme: () => {},
});
theme-toggler-button.js
import {ThemeContext} from './theme-context';
function ThemeTogglerButton() {
// The Theme Toggler Button receives not only the theme
// but also a toggleTheme function from the context
return (
{({theme, toggleTheme}) => (
onClick={toggleTheme}
style={{backgroundColor: theme.background}}>
Toggle Theme
)}
);
}
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 also contains the updater function so it will // be passed down into the context provider this.state = { theme: themes.light, toggleTheme: this.toggleTheme, };
}
render() {
// The entire state is passed to the provider
return (
);
}
}
function Content() {
return (
ReactDOM.render(
使用多個(gè)Contexts
為了保持React的快速渲染,我們需要將每個(gè)consumer組件編寫(xiě)成一個(gè)獨(dú)立的組件節(jié)點(diǎn)(node)
// Theme context, default to light themeconst ThemeContext = React.createContext('light');
// Signed-in user contextconst UserContext = React.createContext({
name: 'Guest',
});
class App extends React.Component {
render() {
const {signedInUser, theme} = this.props;
// App component that provides initial context values return ();
}
}
function Layout() {
return (
// A component may consume multiple contexts
function Content() {
return (
{theme => (
{user => (
)}
)}
);
}
如果有兩個(gè)以上的context經(jīng)常一起使用,我們需要考慮創(chuàng)建一個(gè)render prop component一并提供兩個(gè)Context
注意
因?yàn)閏ontext使用引用標(biāo)示符(reference identity)來(lái)判斷何時(shí)需要重新渲染,所以有些情況下,當(dāng)provider的父元素重新渲染時(shí),會(huì)觸發(fā)consumer的非內(nèi)部渲染。例如下面代碼,在每次Provider重新渲染時(shí),會(huì)重新渲染所有的consumer組件。因?yàn)闀?huì)一直創(chuàng)建一個(gè)新的對(duì)象賦值給value(value一直在變)
class App extends React.Component {
render() {
return (
);
}
}
為了避免這個(gè)問(wèn)題,可以將value放在組件的state中
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: {something: 'something'},
};
}
render() {
return (
);
}
}
感謝各位的閱讀!關(guān)于“Context-React如何跨組件訪問(wèn)數(shù)據(jù)”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。