简单整理React的Context API

之前做项目时经常会遇到某个组件需要传递方法或者数据到其内部的某个子组件,中间跨越了甚至三四层组件,必须层层传递,一不小心哪层组件忘记传递下去了就不行。然而我们的项目其实并没有那么复杂,所以也没有使用redux。这种情况下,使用react本身的Context API来解决数据层层传递问题就很方便啦。

废话不多说,直接来说说这个API怎么用!其实官网文档里写的已经非常清楚了,而且也有examples。我写此篇博客,纯粹就是自己闲着没事整理下罢了。

我们先来看个我写的小demo:

import React, {createContext, PureComponent} from 'react';

const ThemeContext = createContext({
    color: '#f83',
    background: '#EEE'
});
const themes = [
    {
        color: '#f00',
        background: '#efa'
    },
    {
        color: '#06fae5',
        background: '#aae'
    },
    {
        color: '#ef5',
        background: '#cef'
    },
    {
        color: '#fff',
        background: '#000'
    }
];

class ThemedButton extends PureComponent {
    render() {
        return (
            <ThemeContext.Consumer>
                {({theme, changeTheme}) => <button onClick={changeTheme} style={{background: theme.background, color: theme.color}}> It's a button. </button>}
            </ThemeContext.Consumer>
        );
    }
}

class ShowTheme extends PureComponent {
    render() {
        return (
            <ThemeContext.Consumer>
                {({theme, changeTheme}) => <div>
                    <span>color是:{theme.color}</span>
                    <br/>
                    <span>background是:{theme.background}</span>
                </div>}
            </ThemeContext.Consumer>
        );
    }
}

class Header extends PureComponent {
    render() {
        return (
            <div>
                <ThemedButton/>
                <ShowTheme/>
            </div>
        );
    }
}

export default class TestContext extends PureComponent {
    state = {
        themeIndex: 0
    };
    changeTheme = () => {
        const {themeIndex} = this.state;
        const newIndex = themeIndex < themes.length - 1 ? (themeIndex + 1) : 0;
        this.setState({
            themeIndex: newIndex
        });
    };
    render() {
        const {themeIndex} = this.state;

        return (
            <div className="test-test">
                <ThemeContext.Provider value={{
                    theme: themes[themeIndex],
                    changeTheme: this.changeTheme
                }}>
                    <Header />
                </ThemeContext.Provider>
            </div>
        );
    }
}

实现的功能很简单:我预设了4个主题色,点击按钮的时候会按照预设的主题色依次改变button的字体颜色和背景色,并且列出当前所使用的主题色。

接下来简单分析下书面的代码:
1、首先需要导入react的createContext方法,可以传个defaultValue作为默认值作为参数给这个方法,得到了ThemeContext
2、ThemeContext上挂了两个组件:Provider、Consumer,看字面意思就知道一个是供应者、一个是消费者。供应者,就是提供数据的地方。消费者,就是使用数据的地方。
3、Consumer组件必须在Provider的内部,Consumer可以是一个,也可以是多个,上面代码中就有两个Consumer。
4、Consumer的children是一个函数,返回一个组件。函数的参数就是从Provider的value或者defaultValue获取到的数据。
5、Provider可以有,也可以没有。有Provider时,Consumer就会获取Provider的value里的数据。没有Provider时,Consumer就会取调用createContext时作为参数传进去的defaultValue值。
6、Provider的value,不限制啥类型,你传字符串可以,你传map也可以,就看你的业务场景怎么用比较爽。

posted @ 2018-09-26 15:13  Clover.Han  阅读(821)  评论(0编辑  收藏  举报