文章概覽
本文包含新版本react contextAPI的簡單介紹扔役、基本用法和實際項目中的使用方法哺徊。
本文不會介紹context和高階組件的概念构资,而是介紹二者如何配合使用芜壁。
簡介
react在16.3版本引入了全新的context api功茴,提供一種跨組件傳遞數(shù)據(jù)的方法庐冯,避免了在多組件層級間手動傳遞props。
基本用法
項目中很多組件需要共有的狀態(tài)比如:主題坎穿、地區(qū)偏好肄扎。如何優(yōu)雅的處理呢?當(dāng)然了,借助redux犯祠、mobx這些狀態(tài)庫可以輕松實現(xiàn)旭等。但是小項目中無需引入redux等增加復(fù)雜度,讓新手迷惑衡载。
我們考慮使用context如何處理上邊的問題搔耕,下邊的例子為按鈕添加light或dark主題:
- 創(chuàng)建主題context
const THEME = {
light: "light",
dark: "dark",
};
const ThemeContext = React.createContext(THEME.light);
- 使用主題
class ButtonCus extends Component{
render() {
return (
<ThemeContext.Consumer>
{theme => (
<button className={theme}>button</button>
)}
</ThemeContext.Consumer>
);
}
}
現(xiàn)在按鈕使用context創(chuàng)建時默認(rèn)的主題light
,如果想使用dark
主題需要顯示提供Provider
進(jìn)行切換,像這樣:
<ThemeContext.Provider value={THEME.dark}>
<ButtonCus/>
</ThemeContext.Provider>
效果:
context的簡單使用就是這樣
如果每個組件都寫一個Consumer,那將是多么痛苦的事痰娱。有沒有簡潔點的不用每次都寫Consumer弃榨,能不能實現(xiàn)動態(tài)切換主題?
答案是肯定的
接下來將切換主題的接口放入context梨睁,實現(xiàn)在嵌套層級中切換主題鲸睛;將Consumer封裝在高階組件中實現(xiàn)簡潔的使用Consumer;
- 在頂層將當(dāng)前應(yīng)用的主題和切換主題的方法作為context的值向下傳遞
這里需要將組件狀態(tài)作為Provider的值傳遞
class App extends Component{
constructor(props){
super(props);
this.switchTheme = this.switchTheme.bind(this);
//將當(dāng)前應(yīng)用的主題和切換主題的方法作為context的值向下傳遞
this.state = {
theme: THEME.light,
switchTheme: this.switchTheme
};
}
switchTheme() {
this.setState(state => {
return {
theme: state.theme === THEME.light
? THEME.dark
: THEME.light
}
})
}
render(){
return(
<div>
<ThemeContext.Provider value={this.state}>
<ButtonCus/>
<ButtonCus/>
<ButtonCus/>
<ButtonCus/>
</ThemeContext.Provider>
</div>
)
}
}
- 高階組件封裝context的使用邏輯
//高階組件將contest的使用邏輯提取出來坡贺,需要應(yīng)用主題的組件只需像使用普通props一樣使用主題即可
function withContext(Comp) {
return function (props) {
return (
<ThemeContext.Consumer>
{theme => <Comp {...props} theme={theme}/>}
</ThemeContext.Consumer>
)
}
}
- 修改之前的Component 組件
任意組件只要使用withContext包裹后都可以收到名為theme
的屬性官辈,將其應(yīng)用在合適的位置即可。
class ButtonCus extends Component{
render() {
return (
<button
className={this.props.theme.theme}
onClick={this.props.theme.switchTheme}>button
</button>
);
}
}
//使用高階組件將普通組件應(yīng)用上主題, 將高階組件返回的組件賦值為用戶命名組件遍坟,便于使用
ButtonCus = withContext(ButtonCus);
export {ButtonCus}
到此拳亿,點擊任意按鈕都可以切換全局主題。
后記
context有能力處理全局狀態(tài)愿伴,配合高階組件簡化繁瑣的代碼肺魁,意味著小型應(yīng)用完全可以使用context處理全局狀態(tài)。當(dāng)然redux/mobx管理大型應(yīng)用狀態(tài)會更加優(yōu)秀隔节。