このチュートリアルでは、ReactとChatkitを使用してチャットアプリを構築する方法を学びます。
完了したら、タイピングインジケーター、 「Who's Online」リスト、メッセージ履歴を備えたチャットアプリケーションがあります。

これが1つのチュートリアルで取り組むのに多くのように聞こえると思うなら、あなたは通常正しいでしょう!
ただし、Chatkitを使用しているため、Chatkitが重いリフティングを行う間、フロントエンドのReactコードのみに焦点を合わせることができます。
ChatkitはホストされているAPIであり、コードが少ないというアプリケーションに印象的なチャット機能を構築するのに役立ちます。のような機能、
クロスプラットフォームSDKを使用して、すべてのチャットデータがホストされたAPIに送信され、チャット状態を管理し、クライアントにブロードキャストします。

スケールやインフラストラクチャについて心配する必要はありません。私たちはあなたのためにすべての世話をします。
おそらく、Chatkitを学ぶための最良の方法は、構築を開始することですので、フォローすることを強くお勧めします。途中で、ReactでChatkitを使用するときにベストプラクティスを学びます。
このチュートリアルは、段階的にフォローできるように書かれています。合計で12のステップがあります。
これがクイックな要約ですので、あなたは何を期待すべきかを知っています:
さて、コードしましょう!
絶対的なゼロから始めるのではなく、このウォークスルーは最小限のスターターテンプレートに基づいています。

ご覧のとおり、スターターテンプレートには興味深いロジックが含まれていません。反応アプリケーションと単純なノードサーバーを実行するために必要なボイラープレートだけです。
「サーバー?誰もサーバーについて言及していません!」
ノードに精通していない場合は、心配しないでください。次のセクションの後、サーバーにタッチする必要はありません。
開始するには、スターターテンプレートをダウンロードしてから、 npm installを実行します。
git clone https://github.com/pusher/build-a-slack-clone-with-react-and-pusher-chatkit chatkit-tutorial
cd chatkit-tutorial
npm install
(注:完成したコードを表示するには、 completedブランチを表示するか、 git checkout complete実行できます。)
(注:このチュートリアルでは、 npmの使用を想定していますが、同等のyarnコマンドも機能します。)
これで、スターターテンプレートをダウンロードしました。Chatkitインスタンスを作成しましょう。
独自のChatkitインスタンスを作成するには、ダッシュボードにアクセスして新しいCREATION NEW :

インスタンスに名前を付けてください(私はmine "React Chat Tutorial"と呼ばれます)、 [キー]タブのインスタンスロケーターとシークレットキーに注意してください。次のセクションで両方が必要です。
ほとんどのインタラクションはクライアントで発生しますが、Chatkitはユーザーを安全に作成および管理するためのサーバーのカウンターパートも必要です。

このチュートリアルではユーザーを認証することはありませんが、呼び出されたときにChatkitユーザーを作成するルートを定義する必要があります。
@pusher/chatkit-serverをインストールすることから始めます。
npm install --save @pusher/chatkit-server
次に、 ./server.jsを更新します:
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
+ const Chatkit = require('@pusher/chatkit-server')
const app = express()
+ const chatkit = new Chatkit.default({
+ instanceLocator: 'YOUR INSTANCE LOCATOR',
+ key: 'YOUR KEY',
+ })
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(cors())
+ app.post('/users', (req, res) => {
+ const { username } = req.body
+ chatkit
+ .createUser({
+ id: username,
+ name: username
+ })
+ .then(() => res.sendStatus(201))
+ .catch(error => {
+ if (error.error === 'services/chatkit/user_already_exists') {
+ res.sendStatus(200)
+ } else {
+ res.status(error.status).json(error)
+ }
+ })
+ })
+ app.post('/authenticate', (req, res) => {
+ const authData = chatkit.authenticate({ userId: req.query.user_id })
+ res.status(authData.status).send(authData.body)
+ })
const PORT = 3001
app.listen(PORT, err => {
if (err) {
console.error(err)
} else {
console.log(`Running on port ${PORT}`)
}
})「インスタンスロケーター」と「キー」をそれぞれの値に置き換えることを忘れないでください。
ここから開催することがたくさんあります。上から始めてください。
@pusher/chatkit-serverからChatkitをインポートしますchatkitインスタンスをインスタンスにします/usersルートでは、 usernameを取得し、 chatkitインスタンスを通じてチャットキットユーザーを作成します/authenticateて認証されます。リクエストが有効な場合、サーバーはトークン( chatkit.authenticateによって返される)で応答する必要があります。私たちの場合、私たちは - ナイーブに - 誰もが自分が言っている人であると仮定し、 chatkit.authenticateからトークンを返します。ブーム?!サーバーで行う必要があるのはこれだけです。クライアントに移りましょう...
誰かがアプリをロードするとき、私たちは彼らが誰であるかを彼らに尋ねたいと思います。
彼らが送信を押したら、ユーザー名をサーバーに送信し(定義したばかりの/usersルートに)、存在しない場合はchatkitユーザーを作成します。
ユーザーの名前を収集するには、 UsernameForm.js in in ./src/components/というコンポーネントを作成します。
+ import React, { Component } from 'react'
+ class UsernameForm extends Component {
+ constructor(props) {
+ super(props)
+ this.state = {
+ username: '',
+ }
+ this.onSubmit = this.onSubmit.bind(this)
+ this.onChange = this.onChange.bind(this)
+ }
+ onSubmit(e) {
+ e.preventDefault()
+ this.props.onSubmit(this.state.username)
+ }
+ onChange(e) {
+ this.setState({ username: e.target.value })
+ }
+
+ render() {
+ return (
+ <div>
+ <div>
+ <h2>What is your username?</h2>
+ <form onSubmit={this.onSubmit}>
+ <input
+ type="text"
+ placeholder="Your full name"
+ onChange={this.onChange}
+ />
+ <input type="submit" />
+ </form>
+ </div>
+ </div>
+ )
+ }
+ }
+
+ export default UsernameForm次に、 App.jsを更新します:
import React, { Component } from 'react'
+ import UsernameForm from './components/UsernameForm'
class App extends Component {
+ constructor() {
+ super()
+ this.state = {
+ currentUsername: '',
+ }
+ this.onUsernameSubmitted = this.onUsernameSubmitted.bind(this)
+ }
+ onUsernameSubmitted(username) {
+ fetch('http://localhost:3001/users', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ username }),
+ })
+ .then(response => {
+ this.setState({
+ currentUsername: username
+ })
+ })
+ .catch(error => console.error('error', error))
+ }
render() {
- return <h1>Chatly</h1>
+ return <UsernameForm onSubmit={this.onUsernameSubmitted} />
}
}
export default App npm startを使用してアプリケーションを実行すると、画面がレンダリングされていることがわかります。

App.jsの上から始まる:
UsernameFormコンポーネントをインポートします。制御されたコンポーネントと呼ばれる一般的な反応パターンを使用しているため、おそらくおなじみのように見えます。 Reactフォームの詳細については、こちらをご覧くださいrender関数では、 UsernameFormをレンダリングし、 onUsernameSubmittedイベントハンドラーをフックアップしますonUsernameSubmittedが呼び出されると、定義したばかりの/usersルートにpostリクエストを送信します。リクエストが成功した場合は、 this.state.currentUsername更新して、後で参照できるようにします。それ以外の場合は、エラーconsole.error 現時点では、 UsernameFormをレンダリングすると、画面全体が占められています(上記のスクリーンショットを参照)。
ユーザー名が送信されたら、別の画面、つまりチャット画面に移行します。
そのためには、最初にChatScreen.jsコンポーネントを./srcで作成する必要があります。
+ import React, { Component } from 'react'
+
+ class ChatScreen extends Component {
+ render() {
+ return (
+ <div>
+ <h1>Chat</h1>
+ </div>
+ )
+ }
+ }
+
+ export default ChatScreen次に、 App.jsを更新します:
import React, { Component } from 'react'
import UsernameForm from './components/UsernameForm'
+ import ChatScreen from './ChatScreen'
class App extends Component {
constructor() {
super()
this.state = {
currentUsername: '',
+ currentScreen: 'WhatIsYourUsernameScreen'
}
this.onUsernameSubmitted = this.onUsernameSubmitted.bind(this)
}
onUsernameSubmitted(username) {
fetch('http://localhost:3001/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username }),
})
.then(response => {
this.setState({
currentUsername: username,
+ currentScreen: 'ChatScreen'
})
})
.catch(error => console.error('error', error))
}
render() {
+ if (this.state.currentScreen === 'WhatIsYourUsernameScreen') {
return <UsernameForm onSubmit={this.onUsernameSubmitted} />
+ }
+ if (this.state.currentScreen === 'ChatScreen') {
+ return <ChatScreen currentUsername={this.state.currentUsername} />
+ }
}
}
export default Appルーターを使用するのではなく、 this.state.currentScreenに基づいて条件付きで画面をレンダリングします。
以前は、 @pusher/chatkit-serverをインストールしました。今、私たちはクライアントランドにいるので、 @pusher/chatkit-clientもインストールする必要があります。
npm install --save @pusher/chatkit-client
次に、 ChatScreen.jsを更新します:
import React, { Component } from 'react'
+ import Chatkit from '@pusher/chatkit-client'
class ChatScreen extends Component {
+ constructor(props) {
+ super(props)
+ this.state = {
+ currentUser: {}
+ }
+ }
+ componentDidMount () {
+ const chatManager = new Chatkit.ChatManager({
+ instanceLocator: 'YOUR INSTANCE LOCATOR',
+ userId: this.props.currentUsername,
+ tokenProvider: new Chatkit.TokenProvider({
+ url: 'http://localhost:3001/authenticate',
+ }),
+ })
+
+ chatManager
+ .connect()
+ .then(currentUser => {
+ this.setState({ currentUser })
+ })
+ .catch(error => console.error('error', error))
+ }
render() {
return (
<div>
<h1>Chat</h1>
</div>
)
}
}
export default ChatScreen「インスタンスロケーター」を前に注目したあなたのものに置き換えることを忘れないでください。
繰り返しますが、上から始めてください:
ChatkitをインポートしますinstanceLocator 、 userId ( this.props.currentUsernameから)、およびカスタムTokenProviderでChatkit ChatManagerインスタンス化します。 TokenProvider 、以前に定義した/authenticateルートを指しますChatManagerが初期化されたら、 connectを呼び出すことができます。 connect非同期に発生し、 Promiseが返されます。これらの手順に正確に従った場合は、接続します。そうは言っても、何かを逃した場合に備えて、任意のconsole.errorに注意してくださいChatkitを使用すると、すべてのメッセージがChatkitルームに送信されます。
部屋は、プログラムで(クレアターームを使用してサーバーまたはcreateRoomで)、またはダッシュボードインスペクターで作成できます。
検査官から部屋を作成することは本当に良い習慣ではありません(主にテストを目的としています)が、このウォークスルーの目的のために、とにかくそれを行います。
ダッシュボードで、 [コンソール]タブに移動します。そこでは、インスペクターを見つけて、名前のあるユーザーを作成します。私は私の「管理者」と呼びます。
次に、「一般」と呼ばれる部屋を作成します。

上記で強調されたユニークな部屋IDに注意することが本当に重要です。
このステップは、ウォークスルーの重要なポイントをマークします。
これで、ボイラープレートが配置されているため、チャット機能の構築を迅速に開始できます。
今後、各機能を独立した(必要に応じて再利用可能です!)Reactコンポーネントに分類します。

進むときに各コンポーネントを作成しますが、チュートリアルをフォローしやすくするために、基本的なコンポーネントUIレイアウトを今すぐ設定しましょう。
import React, { Component } from 'react'
import Chatkit from '@pusher/chatkit-client'
class ChatScreen extends Component {
constructor(props) {
super(props)
this.state = {
currentUser: {}
}
}
componentDidMount () {
const chatManager = new Chatkit.ChatManager({
instanceLocator: 'YOUR INSTANCE LOCATOR',
userId: this.props.currentUsername,
tokenProvider: new Chatkit.TokenProvider({
url: 'http://localhost:3001/authenticate',
}),
})
chatManager
.connect()
.then(currentUser => {
this.setState({ currentUser })
})
.catch(error => console.error('error', error))
}
render() {
- return (
- <div>
- <h1>Chat</h1>
- </div>
- )
+ const styles = {
+ container: {
+ height: '100vh',
+ display: 'flex',
+ flexDirection: 'column',
+ },
+ chatContainer: {
+ display: 'flex',
+ flex: 1,
+ },
+ whosOnlineListContainer: {
+ width: '300px',
+ flex: 'none',
+ padding: 20,
+ backgroundColor: '#2c303b',
+ color: 'white',
+ },
+ chatListContainer: {
+ padding: 20,
+ width: '85%',
+ display: 'flex',
+ flexDirection: 'column',
+ },
+ }
+ return (
+ <div style={styles.container}>
+ <div style={styles.chatContainer}>
+ <aside style={styles.whosOnlineListContainer}>
+ <h2>Who's online PLACEHOLDER</h2>
+ </aside>
+ <section style={styles.chatListContainer}>
+ <h2>Chat PLACEHOLDER</h2>
+ </section>
+ </div>
+ </div>
+ )
}
}
export default ChatScreen今すぐアプリを実行すると、基本的なレイアウトが行われることがわかります。

素晴らしい!
これをお見せして本当に興奮しています!
Chatkit接続ができました。チャット機能の構築は、ChatkitイベントをUIコンポーネントに接続するのと同じくらい簡単になりました。ここで、お見せしましょう。
まず、Stateless MessageList.jsコンポーネントを./src/componentsに作成します。
+ import React, { Component } from 'react'
+
+ class MessagesList extends Component {
+ render() {
+ const styles = {
+ container: {
+ overflowY: 'scroll',
+ flex: 1,
+ },
+ ul: {
+ listStyle: 'none',
+ },
+ li: {
+ marginTop: 13,
+ marginBottom: 13,
+ },
+ senderUsername: {
+ fontWeight: 'bold',
+ },
+ message: { fontSize: 15 },
+ }
+ return (
+ <div
+ style={{
+ ...this.props.style,
+ ...styles.container,
+ }}
+ >
+ <ul style={styles.ul}>
+ {this.props.messages.map((message, index) => (
+ <li key={index} style={styles.li}>
+ <div>
+ <span style={styles.senderUsername}>{message.senderId}</span>{' '}
+ </div>
+ <p style={styles.message}>{message.text}</p>
+ </li>
+ ))}
+ </ul>
+ </div>
+ )
+ }
+ }
+
+ export default MessagesList次に、 ChatScreen.jsを更新します:
import React, { Component } from 'react'
import Chatkit from '@pusher/chatkit-client'
+ import MessageList from './components/MessageList'
class ChatScreen extends Component {
constructor(props) {
super(props)
this.state = {
currentUser: {},
+ currentRoom: {},
+ messages: []
}
}
componentDidMount () {
const chatManager = new Chatkit.ChatManager({
instanceLocator: 'YOUR INSTANCE LOCATOR',
userId: this.props.currentUsername,
tokenProvider: new Chatkit.TokenProvider({
url: 'http://localhost:3001/authenticate',
}),
})
chatManager
.connect()
.then(currentUser => {
this.setState({ currentUser })
+ return currentUser.subscribeToRoom({
+ roomId: "YOUR ROOM ID",
+ messageLimit: 100,
+ hooks: {
+ onMessage: message => {
+ this.setState({
+ messages: [...this.state.messages, message],
+ })
+ },
+ },
+ })
+ })
+ .then(currentRoom => {
+ this.setState({ currentRoom })
+ })
.catch(error => console.error('error', error))
}
render() {
const styles = {
...
}
return (
<div style={styles.container}>
<div style={styles.chatContainer}>
<aside style={styles.whosOnlineListContainer}>
<h2>Who's online PLACEHOLDER</h2>
</aside>
<section style={styles.chatListContainer}>
- <h2>Chat PLACEHOLDER</h2>
+ <MessageList
+ messages={this.state.messages}
+ style={styles.chatList}
+ />
</section>
</div>
</div>
)
}
}
export default ChatScreen以前に注目した自分の部屋IDに部屋のIDを置き換えることを忘れないでください。
それを分解しましょう:
currentUserオブジェクトを取得しますcurrentUserで発生するということですcurrentUser ( currentUser.subscribeToRoom )でsubscribeToRoom電話しますsubscribeToRoom 、新しいメッセージが到着するたびにリアルタイムで呼ばれるonMessageと呼ばれるイベントハンドラーを取りますmessageLimit 100であることを指定したため、最新のonMessageに対しては、最新の100に対しても遡及的に呼ばれます。実際には、これはページを更新すると、最新のチャットメッセージが最大100表示されることを意味します。私たちはロールしています!
次に、最初にSendMessageForm.jsコンポーネントを./src/componentsで作成してメッセージを送信できるようにしましょう。
+ import React, { Component } from 'react'
+
+ class SendMessageForm extends Component {
+ constructor(props) {
+ super(props)
+ this.state = {
+ text: '',
+ }
+ this.onSubmit = this.onSubmit.bind(this)
+ this.onChange = this.onChange.bind(this)
+ }
+
+ onSubmit(e) {
+ e.preventDefault()
+ this.props.onSubmit(this.state.text)
+ this.setState({ text: '' })
+ }
+
+ onChange(e) {
+ this.setState({ text: e.target.value })
+ if (this.props.onChange) {
+ this.props.onChange()
+ }
+ }
+
+ render() {
+ const styles = {
+ container: {
+ padding: 20,
+ borderTop: '1px #4C758F solid',
+ marginBottom: 20,
+ },
+ form: {
+ display: 'flex',
+ },
+ input: {
+ color: 'inherit',
+ background: 'none',
+ outline: 'none',
+ border: 'none',
+ flex: 1,
+ fontSize: 16,
+ },
+ }
+ return (
+ <div style={styles.container}>
+ <div>
+ <form onSubmit={this.onSubmit} style={styles.form}>
+ <input
+ type="text"
+ placeholder="Type a message here then hit ENTER"
+ onChange={this.onChange}
+ value={this.state.text}
+ style={styles.input}
+ />
+ </form>
+ </div>
+ </div>
+ )
+ }
+ }
+
+ export default SendMessageFormそれから - あなたはそれを推測しましたChatScreen.jsを更新:
import React, { Component } from 'react'
import Chatkit from '@pusher/chatkit-client'
import MessageList from './components/MessageList'
+ import SendMessageForm from './components/SendMessageForm'
class ChatScreen extends Component {
constructor(props) {
super(props)
this.state = {
currentUser: {},
currentRoom: {},
messages: []
}
+ this.sendMessage = this.sendMessage.bind(this)
}
+ sendMessage(text) {
+ this.state.currentUser.sendMessage({
+ text,
+ roomId: this.state.currentRoom.id,
+ })
+ }
componentDidMount () {
const chatManager = new Chatkit.ChatManager({
instanceLocator: 'YOUR INSTANCE LOCATOR',
userId: this.props.currentUsername,
tokenProvider: new Chatkit.TokenProvider({
url: 'http://localhost:3001/authenticate',
}),
})
chatManager
.connect()
.then(currentUser => {
this.setState({ currentUser })
return currentUser.subscribeToRoom({
roomId: YOUR ROOM ID,
messageLimit: 100,
hooks: {
onMessage: message => {
this.setState({
messages: [...this.state.messages, message],
})
},
},
})
})
.then(currentRoom => {
this.setState({ currentRoom })
})
.catch(error => console.error('error', error))
}
render() {
const styles = {
...
}
return (
<div style={styles.container}>
<div style={styles.chatContainer}>
<aside style={styles.whosOnlineListContainer}>
<h2>Who's online PLACEHOLDER</h2>
</aside>
<section style={styles.chatListContainer}>
<MessageList
messages={this.state.messages}
style={styles.chatList}
/>
+ <SendMessageForm onSubmit={this.sendMessage} />
</section>
</div>
</div>
)
}
}
export default ChatScreen SendMessageFormコンポーネントは、以前に定義したWhatIsYourUsernameFormコンポーネントと本質的に同じです。
SendMessageFormが送信されると、 this.state.currentUserにアクセスし、 sendMessageを呼び出します(ほとんどの相互作用はcurrentUserで発生することを忘れないでください)
おそらくパターンが出現するのを見ることができます...
ChatScreen 、アプリケーション状態を管理し、プレゼンテーション(通常はステートレス)コンポーネントを使用してUIをレンダリングするコンテナコンポーネントです。私たちのコードのほとんどは、Chatkitイベントとそれに関連するデータを接続して、UIコンポーネントを反応させることを伴います。
独自のタイピングインジケーターを実装しようとしたことがある場合は、トリッキーであることがわかります。一般に、よりリアルタイムの機能により、より多くのデータとより多くの接続を管理することができます。
Chatkitを使用すると、ほとんど労力でタイピングインジケーターを追加できます。
./src/componentsでTypingIndicator.jsコンポーネントを作成することから始めます。
+ import React, { Component } from 'react'
+
+ class TypingIndicator extends Component {
+ render() {
+ if (this.props.usersWhoAreTyping.length > 0) {
+ return (
+ <div>
+ {`${this.props.usersWhoAreTyping
+ .slice(0, 2)
+ .join(' and ')} is typing`}
+ </div>
+ )
+ }
+ return <div />
+ }
+ }
+
+ export default TypingIndicator次に、 ChatScreen.jsを更新します:
import React, { Component } from 'react'
import Chatkit from '@pusher/chatkit-client'
import MessageList from './components/MessageList'
import SendMessageForm from './components/SendMessageForm'
+ import TypingIndicator from './components/TypingIndicator'
class ChatScreen extends Component {
constructor(props) {
super(props)
this.state = {
currentUser: {},
currentRoom: {},
messages: [],
+ usersWhoAreTyping: [],
}
this.sendMessage = this.sendMessage.bind(this)
+ this.sendTypingEvent = this.sendTypingEvent.bind(this)
}
+ sendTypingEvent() {
+ this.state.currentUser
+ .isTypingIn({ roomId: this.state.currentRoom.id })
+ .catch(error => console.error('error', error))
+ }
sendMessage(text) {
this.state.currentUser.sendMessage({
text,
roomId: this.state.currentRoom.id,
})
}
componentDidMount() {
const chatManager = new Chatkit.ChatManager({
instanceLocator: 'YOUR INSTANCE LOCATOR',
userId: this.props.currentUsername,
tokenProvider: new Chatkit.TokenProvider({
url: 'http://localhost:3001/authenticate',
}),
})
chatManager
.connect()
.then(currentUser => {
this.setState({ currentUser })
return currentUser.subscribeToRoom({
roomId: YOUR ROOM ID,
messageLimit: 100,
hooks: {
onMessage: message => {
this.setState({
messages: [...this.state.messages, message],
})
},
+ onUserStartedTyping: user => {
+ this.setState({
+ usersWhoAreTyping: [...this.state.usersWhoAreTyping, user.name],
+ })
+ },
+ onUserStoppedTyping: user => {
+ this.setState({
+ usersWhoAreTyping: this.state.usersWhoAreTyping.filter(
+ username => username !== user.name
+ ),
+ })
+ },
},
})
})
.then(currentRoom => {
this.setState({ currentRoom })
})
.catch(error => console.error('error', error))
}
render() {
const styles = {
...
}
return (
<div style={styles.container}>>
<div style={styles.chatContainer}>
<aside style={styles.whosOnlineListContainer}>
<h2>Who's online PLACEHOLDER</h2>
</aside>
<section style={styles.chatListContainer}>
<MessageList
messages={this.state.messages}
style={styles.chatList}
/>
+ <TypingIndicator usersWhoAreTyping={this.state.usersWhoAreTyping} />
<SendMessageForm
onSubmit={this.sendMessage}
+ onChange={this.sendTypingEvent}
/>
</section>
</div>
</div>
)
}
}
export default ChatScreenChatkitを使用する場合、インジケータのタイピングは2つの基本的なアクションに要約されます。
currentUser.userIsTypingを呼び出します。それから、userStartedTypingを聴き、 userStoppedTypingイベントを聴いていますそして、それはほとんどそれです。
「しかし、アレックス、ユーザーがタイピングを停止したときはどうですか?」
それはとても良い質問です。
Chatkitはそのように賢いです。サービスが数秒後にuserIsTypingイベントを受信しない場合、 currentUserタイピングを停止したと想定しています。したがって、誰かがタイピングを停止したときに手動でイベントを提起する必要はありません。かなり滑らかですよね?
勢いを感じることができますか?もうやった?
チャットアプリを完了するには、Chatkitの「Who's Online」機能を使用して、ユーザーのリストとリアルタイムのオンラインステータスをレンダリングしましょう。
/src/componentsでWhosOnlineList.jsコンポーネントを作成することから始めます。
+ import React, { Component } from 'react'
+
+ class WhosOnlineList extends Component {
+ renderUsers() {
+ return (
+ <ul>
+ {this.props.users.map((user, index) => {
+ if (user.id === this.props.currentUser.id) {
+ return (
+ <WhosOnlineListItem key={index} presenceState="online">
+ {user.name} (You)
+ </WhosOnlineListItem>
+ )
+ }
+ return (
+ <WhosOnlineListItem key={index} presenceState={user.presence.state}>
+ {user.name}
+ </WhosOnlineListItem>
+ )
+ })}
+ </ul>
+ )
+ }
+
+ render() {
+ if (this.props.users) {
+ return this.renderUsers()
+ } else {
+ return <p>Loading...</p>
+ }
+ }
+ }
+
+ class WhosOnlineListItem extends Component {
+ render() {
+ const styles = {
+ li: {
+ display: 'flex',
+ alignItems: 'center',
+ marginTop: 5,
+ marginBottom: 5,
+ paddingTop: 2,
+ paddingBottom: 2,
+ },
+ div: {
+ borderRadius: '50%',
+ width: 11,
+ height: 11,
+ marginRight: 10,
+ },
+ }
+ return (
+ <li style={styles.li}>
+ <div
+ style={{
+ ...styles.div,
+ backgroundColor:
+ this.props.presenceState === 'online' ? '#539eff' : '#414756',
+ }}
+ />
+ {this.props.children}
+ </li>
+ )
+ }
+ }
+
+ export default WhosOnlineListそれなら - 最後に? ChatScreen.jsを更新:
import React, { Component } from 'react'
import Chatkit from '@pusher/chatkit-client'
import MessageList from './components/MessageList'
import SendMessageForm from './components/SendMessageForm'
import TypingIndicator from './components/TypingIndicator'
+ import WhosOnlineList from './components/WhosOnlineList'
class ChatScreen extends Component {
constructor(props) {
super(props)
this.state = {
currentUser: {},
currentRoom: {},
messages: [],
usersWhoAreTyping: [],
}
this.sendMessage = this.sendMessage.bind(this)
this.sendTypingEvent = this.sendTypingEvent.bind(this)
}
sendTypingEvent() {
this.state.currentUser
.isTypingIn(this.state.currentRoom.id)
.catch(error => console.error('error', error))
}
sendMessage(text) {
this.state.currentUser.sendMessage({
text,
roomId: this.state.currentRoom.id,
})
}
comonentDidMount() {
const chatManager = new Chatkit.ChatManager({
instanceLocator: 'YOUR INSTANCE LOCATOR',
userId: this.props.currentUsername,
tokenProvider: new Chatkit.TokenProvider({
url: 'http://localhost:3001/authenticate',
}),
})
chatManager
.connect()
.then(currentUser => {
this.setState({ currentUser })
return currentUser.subscribeToRoom({
roomId: YOUR ROOM ID,
messageLimit: 100,
hooks: {
newMessage: message => {
this.setState({
messages: [...this.state.messages, message],
})
},
userStartedTyping: user => {
this.setState({
usersWhoAreTyping: [...this.state.usersWhoAreTyping, user.name],
})
},
userStoppedTyping: user => {
this.setState({
usersWhoAreTyping: this.state.usersWhoAreTyping.filter(
username => username !== user.name
),
})
},
+ onPresenceChange: () => this.forceUpdate(),
},
})
})
.then(currentRoom => {
this.setState({ currentRoom })
})
.catch(error => console.error('error', error))
}
render() {
const styles = {
...
}
return (
<div style={styles.container}>
<header style={styles.header}>
<h2>Chatly</h2>
</header>
<div style={styles.chatContainer}>
<aside style={styles.whosOnlineListContainer}>
- <h2>Who's online PLACEHOLDER</h2>
+ <WhosOnlineList
+ currentUser={this.state.currentUser}
+ users={this.state.currentRoom.users}
+ />
</aside>
<section style={styles.chatListContainer}>
<MessageList
messages={this.state.messages}
style={styles.chatList}
/>
<TypingIndicator usersWhoAreTyping={this.state.usersWhoAreTyping} />
<SendMessageForm
onSubmit={this.sendMessage}
onChange={this.sendTypingEvent}
/>
</section>
</div>
</div>
)
}
}
export default ChatScreen React状態でユーザーの状態を管理するのは少し難しい場合があるため、 currentRoom.usersで管理します。
ユーザーが接続して切断されると、このプロパティは動的に更新されます。言い換えれば、 currentRoom.users常にチャットアプリの現在の状態を再構築する必要があります。
したがって、ユーザーがオンラインになったり、オフラインになったり( onPresenceChange )、または新しいユーザーが参加し( onUserAdded )、 currentRoom.usersを評価してUIを更新するようにReactを伝えるCall forceUpdateだけです。
繰り返しますが、それは本当にいくつかの簡単なデータとイベントを配線してコンポーネントを反応させることになります。それだけです。
このウォークスルーでは、完全なチャットアプリケーションを作成しました
Chatkitを使用したため、ボーナス機能も無料で入手できます。
かなりの量のコードを書きましたが、どれも特に複雑ではありませんでした。
Chatkitには、すべてのチャットデータを管理する最小限の強力なAPIがあります。私たちがしなければならなかったのは、そのデータを取得してユーザーにレンダリングすることです。
構築し続けたいですか?豊富なメディアサポートを追加して領収書を読んでみませんか? Chatkitは両方をサポートしています:
また、私たちの強力なChatkit Slackデモ(250+星€€)をチェックすることに興味があるかもしれません。これは、私たちが構築したばかりですが、より完全なアプリケーションに似ています。
Chatkitで何を構築しますか?見たいです!あなたのフィードバックは、Chatkitの改善に私たちを導きます。目標に到達するのに役立つもの、邪魔になっていること、または欠けているものを教えてください。