0x000 概述
Context
就是全局state
啦~~
0x001 問題
先上栗子,我們需要在Topbar
中用到theme
,但是theme
必須從最外層傳入,所以必須從最外層傳入App
,再傳入TopBar
,這隻傳遞了兩次,但是如果全部組件都需要theme
呢?或者有一個非常深的組件需要theme
,而中間的大部分組件都不需要theme
呢?爲了傳遞這個theme
必須一層一層的傳遞下去,有點難受。
class TopBar extends React.Component {
redder() {
return <div>
{this.props.theme}
</div>
}
}
class App extends React.Component {
render() {
return <div>
<TopBar theme={this.props.theme}/>
</div>
}
}
ReactDom.render(
<App theme='dark'/>,
document.getElementById('app')
)
0x002 解決
Context
可以解決這個問題,上栗子:
-
創建
context
const ThemeContext = React.createContext('theme');
React.createContext
創建了一個context
,它返回一個對象,可以打印出來:
需要注意的是:-
Consumer
:消費者 -
Provider
:提供者
-
-
創建提供者
class App extends React.Component { constructor(props) { super(props); this.state = { theme: 'dark' } } render() { return ( <ThemeContext.Provider value={this.state.theme}> <ThemedButton/> <button onClick={() => this.handleChangeTheme()} className='btn btn-primary'> 修改主題</button> </ThemeContext.Provider> ); } handleChangeTheme() { this.setState({ theme: this.state.theme === 'light' ? 'dark' : 'light' }) } }
ThemeContext.Provider
是一個組件,value
屬性提供的值在所有的Consumer
中都可以訪問到,前提是必須包裹在Provider
中。 -
創建消費者
class ThemedButton extends React.Component { render() { return <ThemeContext.Consumer> { (value) => <div>{value}</div> } </ThemeContext.Consumer> } }
ThemeContext.consumer
是一個組件,包裹在其中的函數組件可以訪問到ThemeContext.Provider
聲明時候傳入的value
,並且在ThemeContext.Provider
的value
變動的時候,再次渲染。 -
使用
ReactDom.render( <App theme='dark'/>, document.getElementById('app') )
- 效果
-
整個栗子:
import ReactDom from 'react-dom' import React from 'react' const ThemeContext = React.createContext('theme'); class ThemedButton extends React.Component { render() { return <ThemeContext.Consumer> { (value) => <div>{value}</div> } </ThemeContext.Consumer> } } class App extends React.Component { constructor(props) { super(props); this.state = { theme: 'dark' } } render() { return ( <ThemeContext.Provider value={this.state.theme}> <ThemedButton/> <button onClick={() => this.handleChangeTheme()} className='btn btn-primary'> 修改主題</button> </ThemeContext.Provider> ); } handleChangeTheme() { this.setState({ theme: this.state.theme === 'light' ? 'dark' : 'light' }) } } ReactDom.render( <App theme='dark'/>, document.getElementById('app') )