使用React Context进行状态管理(四)使用多个React Context Provider

首先确认一点,Context是可以嵌套使用的,因为Context也是Component,当然可以嵌套。

创建MessageContext.js,也就是共享Message相关的变量和函数。代码如下:

const { Provider, Consumer } = React.createContext()

class MessageProvider extends React.Component {
    state = {
        messages: [],
        currentMessage: null,
        error: null,
        loading: false
    }

    componentDidMount() {
        this.setState({ loading: true, error: null })
        getMessages()
            .then(messages => this.setState({ loading: false, messages }))
            .catch(error => this.setState({ loading: false, error }))
    }

    selectMessageHandler = (message) => {
        this.setState({ currentMessage: message })
    }

    render() {
        return (
            <Provider value={{
                ...this.state,
                onSelectMessage: this.selectMessageHandler
            }}>{this.props.children}</Provider>
        )
    }
}

export { MessageProvider, Consumer as MessageConsumer }

没什么可讲的,getMessages函数是helper.js里新加的内容,用来模拟api调用的,代码如下:

export const Messages = [
    {
        id: 0,
        subject: 'Message1',
        body: 'Message1'
    },
    {
        id: 1,
        subject: 'Message2',
        body: 'Message2'
    },
    {
        id: 2,
        subject: 'Message3',
        body: 'Message3'
    }
]

export function getMessages() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(Messages)
        }, 1000);
    })
}

在ReactDom.render函数中,我们来使用新创建的MessageProvider,作为UserProvider的子组件:

ReactDOM.render(
    <UserProvider>
        <MessageProvider>
            <App />
        </MessageProvider>
    </UserProvider>,
    document.getElementById('root')
);

然后我们一边来补充完成应用,一边来使用MessageConsumer。

添加Message组件,作为MessageList的子组件。代码如下:

const Message = ({ message, onClick }) => (
    <li onClick={onClick}>
        <div>{message.subject}</div>
    </li>
)

Message组件会显示信息标题,我们这里就直接传入整个message了;有onClick属性,即点击该条message会显示具体内容。

添加MessageDetails组件,即显示message的具体内容,这里使用了MessageConsumer,代码如下:

const MessageDetails = () => (
    <MessageConsumer>
        {({ currentMessage, onSelectMessage }) => (
            <div>
                <button onClick={() => onSelectMessage(null)}>
                    Back
        </button>
                <h3>{currentMessage.subject}</h3>
                <div>{currentMessage.body}</div>
            </div>
        )}
    </MessageConsumer>
)

最后看下MessageList组件:

<UserConsumer>
        {
            ({ user }) => (
                <MessageConsumer>
                    {
                        ({ loading, messages, onSelectMessage }) => (
                            <div>
                                {
                                    loading ? <div>加载中......</div> :
                                        messages.length === 0 ? <div>没有信息, {user.name}</div> :
                                            <ul>
                                                {messages.map(message => <Message key={message.id} message={message} onClick={() => onSelectMessage(message)} />)}
                                            </ul>
                                }

                            </div>
                        )
                    }
                </MessageConsumer>
            )
        }
    </UserConsumer>

这里我们看到了Consumer的嵌套使用,Consumer的嵌套看起来更像函数闭包的应用,因为Consumer包裹的是个函数,子Consumer被包裹在父Consumer的函数里,并使用了父Consumer函数中的变量user。其他的没啥可说的,解构对象,给组件属性赋值等等。

下一次我们看看Context的Provider和Consumer的配对使用问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,621评论 1 32
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 7,295评论 0 17
  • 深入JSX date:20170412笔记原文其实JSX是React.createElement(componen...
    gaoer1938阅读 8,175评论 2 35
  • 今天发生的三件好事: 1.中午和儿子们一起吃饭,很开心。 2.下午去希诺丝体验店做护理,很享受。 3.晚上老乡请吃...
    819d60284d13阅读 215评论 0 1
  • 1.能让你精致的,除了化妆品,最厉害的是知识、努力和爱。 2.适当降低期望值 生活就是那样,天不从人愿,事不从人心...
    adieues阅读 647评论 3 7

友情链接更多精彩内容