React入門0x013: Context

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,它返回一個對象,可以打印出來:

    clipboard.png
    需要注意的是:

    • 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.Providervalue變動的時候,再次渲染。

  • 使用

    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')
    )
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章