0x000 overview
Context
Is the overall situation.state
La~~0x001 problem
First, we need the chestnuts
Topbar
Used intheme
,howevertheme
Must be passed in from the outermost, so it must be passed in from the outermostApp
,Re introductionTopBar
,This is only passed twice, but if all components need totheme
What about it? Or a very deep component needstheme
,Most of the components in the middle don't need totheme
What about it? To deliver thistheme
It must be passed down layer by layer. It's a bit uncomfortable.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 solution
Context can solve this problem
-
Create context
const ThemeContext = React.createContext('theme');
React.createContext creates a context, which returns an object that can be printed out:
It should be noted that:- Consumer: Consumer
- Provider: Provider
-
Create 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'> Modify theme</button> </ThemeContext.Provider> ); } handleChangeTheme() { this.setState({ theme: this.state.theme === 'light' ? 'dark' : 'light' }) } }
ThemeContext.Provider is a component. The value provided by the value attribute can be accessed in all consumers, provided it is wrapped in the Provider.
-
Create consumer
class ThemedButton extends React.Component { render() { return <ThemeContext.Consumer> { (value) => <div>{value}</div> } </ThemeContext.Consumer> } }
ThemeContext.consumer is a component. The function component wrapped in it can access the value passed in when ThemeContext.Provider is declared, and render again when the value of ThemeContext.Provider changes.
-
Use
ReactDom.render( <App theme='dark'/>, document.getElementById('app') )
- Effect
-
Whole Chestnut:
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'> Modify theme</button> </ThemeContext.Provider> ); } handleChangeTheme() { this.setState({ theme: this.state.theme === 'light' ? 'dark' : 'light' }) } } ReactDom.render( <App theme='dark'/>, document.getElementById('app') )