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')
    )

followWinter
1.5k 声望82 粉丝

暂时没有