React Contextによる状態管理(六)Contextによる通知効果
7426 ワード
Windowsシステムの右下にポップアップ通知、Macシステムの右上にポップアップ通知、iPhoneに上部通知、Androidに下部通知があることを知っています.Reactアプリでもこのような機能を実現したいなら、Contextが最適です.どうして似合うの?Contextの出現は共有状態管理を解決するためではないでしょうか.通知機能は、すべてのコンポーネントが共有する機能ではないでしょうか.各コンポーネントに通知コンポーネントを書くのは難しいですか?
一言も言わずにNotificationContextを作成します.
NotificationContextにはメッセージ・オブジェクトを格納するメッセージ・ステータス変数があり、addMessage関数は新しいメッセージを追加するために使用され、removeMessage関数はメッセージを削除するために使用されます.Notificationコンポーネントは、メッセージの内容と閉じるボタンを含むメッセージの表示をカプセル化するために使用されます.
新しいニュースをシミュレートするためにhelperにいます.jsにgetLatestMessagesの関数を追加します.
ここではsliceを用いて1つの情報のみを含む配列を取得する.
では、MessageContext.を見てみましょう.js.
すべてのメッセージを取得した後、5秒ごとに先ほどのhelperの新しいメッセージ生成関数を呼び出し、newMessage関数に論理をカプセル化しました.
新しいメッセージがある場合は、既存のメッセージリストに追加し、通知を表示する関数notifyを呼び出します.notify関数は、MessageProviderコンポーネントに属性的に渡されるNotificationProviderのaddMessage関数です.しかし、ここでは、MetsageProviderに関数を渡すためにNotificationConsumerを使用するのではなく、高次コンポーネントを使用します.NotificationContextの最終コードは次のとおりです.
MessageContextでwithNotifier関数をインポートすると、最終コードは次のようになります.
新しく追加された内容では、withNotify関数、MessageProviderをパラメータとして使用し、関数はnotifyプロパティ、すなわちNotifyプロパティを持つaddMessage関数をMessageProviderに渡すことを示します.
最後にReactDOMでrender関数にルートコンポーネントとしてNotificationProviderコンポーネントを追加します.
これで、グローバル通知機能付きのAppが完了します.
一言も言わずにNotificationContextを作成します.
import React from 'react'
const { Provider, Consumer } = React.createContext()
class NotificationProvider extends React.Component {
state = {
messages: []
}
addMessage = text => {
this.setState(state => ({
messages: [
...state.messages,
{
id: Math.random(),
text
}
]
}))
}
removeMessage = message => {
this.setState(state => ({
messages: state.messages.filter(msg => (
msg.id !== message.id
))
}))
}
render() {
return (
{this.state.messages.map(message => (
this.removeMessage(message)}
>
))}
{this.props.children}
)
}
}
const Notification = ({ message, onClose }) => (
{message.text}
)
NotificationContextにはメッセージ・オブジェクトを格納するメッセージ・ステータス変数があり、addMessage関数は新しいメッセージを追加するために使用され、removeMessage関数はメッセージを削除するために使用されます.Notificationコンポーネントは、メッセージの内容と閉じるボタンを含むメッセージの表示をカプセル化するために使用されます.
新しいニュースをシミュレートするためにhelperにいます.jsにgetLatestMessagesの関数を追加します.
export function getLatestMessages() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(
Messages.map(msg => ({
...msg,
id: Math.random()
})).slice(
0,
1
)
);
}, 1000);
});
}
ここではsliceを用いて1つの情報のみを含む配列を取得する.
では、MessageContext.を見てみましょう.js.
componentDidMount() {
this.setState({ loading: true, error: null })
getMessages()
.then(messages => this.setState({ loading: false, messages }))
.catch(error => this.setState({ loading: false, error }))
//
this.newMessageInterval = setInterval(this.newMessage, 5000)
}
すべてのメッセージを取得した後、5秒ごとに先ほどのhelperの新しいメッセージ生成関数を呼び出し、newMessage関数に論理をカプセル化しました.
newMessage = () => {
if (!this.state.loading) {
getLatestMessages()
.then(message => {
this.setState(state => ({ messages: state.messages.concat(message) }))
this.props.notify(` `)
})
}
}
新しいメッセージがある場合は、既存のメッセージリストに追加し、通知を表示する関数notifyを呼び出します.notify関数は、MessageProviderコンポーネントに属性的に渡されるNotificationProviderのaddMessage関数です.しかし、ここでは、MetsageProviderに関数を渡すためにNotificationConsumerを使用するのではなく、高次コンポーネントを使用します.NotificationContextの最終コードは次のとおりです.
import React from 'react'
const { Provider, Consumer } = React.createContext()
class NotificationProvider extends React.Component {
state = {
messages: []
}
addMessage = text => {
this.setState(state => ({
messages: [
...state.messages,
{
id: Math.random(),
text,
}
]
}))
}
removeMessage = message => {
this.setState(state => ({
messages: state.messages.filter(msg => (
msg.id !== message.id
))
}))
}
render() {
return (
{this.state.messages.map(message => (
this.removeMessage(message)}
>
))}
{this.props.children}
)
}
}
const Notification = ({ message, onClose }) => (
{message.text}
)
//
function withNotifier(Component) {
return function Notified(props) {
return (
{
({ notify }) => (
)
}
)
}
}
export { NotificationProvider, Consumer as NotificationConsumer, withNotifier }
MessageContextでwithNotifier関数をインポートすると、最終コードは次のようになります.
import React from 'react'
import { getMessages, getLatestMessages } from './helper'
import { withNotifier } from './NotificationContext'
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 }))
this.newMessageInterval = setInterval(this.newMessage, 5000)
}
componentWillUnmount() {
clearInterval(this.newMessage)
}
selectMessageHandler = (message) => {
this.setState({ currentMessage: message })
}
newMessage = () => {
if (!this.state.loading) {
getLatestMessages()
.then(message => {
this.setState(state => ({ messages: state.messages.concat(message) }))
this.props.notify(` `)
})
}
}
render() {
return (
{this.props.children}
)
}
}
//
const MessageWithNotifierProvider = withNotifier(MessageProvider)
export { MessageWithNotifierProvider as MessageProvider, Consumer as MessageConsumer }
新しく追加された内容では、withNotify関数、MessageProviderをパラメータとして使用し、関数はnotifyプロパティ、すなわちNotifyプロパティを持つaddMessage関数をMessageProviderに渡すことを示します.
最後にReactDOMでrender関数にルートコンポーネントとしてNotificationProviderコンポーネントを追加します.
ReactDOM.render(
,
document.getElementById('root')
);
これで、グローバル通知機能付きのAppが完了します.