美文网首页
使用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