美文网首页
使用React Context进行状态管理(四)使用多个Reac

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

作者: du1dume | 来源:发表于2019-05-07 08:51 被阅读0次

    首先确认一点,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的配对使用问题。

    相关文章

      网友评论

          本文标题:使用React Context进行状态管理(四)使用多个Reac

          本文链接:https://www.haomeiwen.com/subject/ffysoqtx.html