Dalam tutorial ini, Anda akan belajar cara membangun aplikasi obrolan dengan React dan Chatkit.
Setelah selesai, kami akan memiliki aplikasi obrolan lengkap dengan indikator pengetikan , daftar "siapa online" , dan riwayat pesan :

Jika Anda pikir ini terdengar banyak untuk ditangani dalam satu tutorial, Anda biasanya benar!
Namun, karena kami akan menggunakan ChatKit, kami dapat lebih atau kurang fokus secara eksklusif pada kode reaksi front-end sementara ChatKit melakukan pengangkatan berat.
ChatKit adalah API yang di -host yang membantu Anda membangun fitur obrolan yang mengesankan ke dalam aplikasi Anda dengan lebih sedikit kode. Fitur seperti,
Menggunakan SDK lintas platform kami, semua data obrolan dikirim ke API yang di-host kami di mana kami mengelola status obrolan dan menyiarkannya ke klien Anda:

Anda tidak perlu khawatir tentang skala atau infrastruktur, kami mengurus semuanya untuk Anda.
Mungkin cara terbaik untuk belajar Chatkit adalah dengan mulai membangun, jadi saya sangat menyarankan Anda mengikuti. Sepanjang jalan, Anda akan belajar praktik terbaik saat menggunakan ChatKit dengan React.
Tutorial ini telah ditulis sehingga Anda dapat mengikuti, langkah demi langkah. Ada 12 langkah secara total.
Berikut ringkasan singkat jadi Anda tahu apa yang diharapkan:
Baiklah, mari kita kode!
Daripada memulai dari goresan absolut, walkthrough ini didasarkan pada template starter minimal:

Seperti yang Anda lihat, template starter tidak mengandung logika yang menarik - cukup boilerplate kita perlu menjalankan aplikasi bereaksi dan server simpul sederhana.
"Server? Tidak ada yang menyebutkan server!"
Jika Anda tidak terlalu terbiasa dengan Node, jangan khawatir? Setelah bagian berikutnya, kami tidak perlu menyentuh server.
Untuk memulai, unduh template starter lalu jalankan npm install :
git clone https://github.com/pusher/build-a-slack-clone-with-react-and-pusher-chatkit chatkit-tutorial
cd chatkit-tutorial
npm install
(Catatan: Untuk melihat kode yang sudah selesai, Anda dapat melihat cabang completed atau menjalankan git checkout complete secara lokal.)
(Juga Catatan: Tutorial ini mengasumsikan penggunaan npm , tetapi perintah yarn yang setara akan berfungsi juga.)
Sekarang Anda telah mengunduh templat starter, mari kita buat instance chatkit.
Untuk membuat instance ChatKit Anda sendiri, pergilah ke dasbor dan tekan Buat Baru :

Berikan instance Anda nama apa pun (saya memanggil saya "react chat tutorial") kemudian perhatikan pencari locator instance Anda dan kunci rahasia di tab Keys . Kami akan membutuhkan keduanya di bagian selanjutnya.
Sementara sebagian besar interaksi akan terjadi pada klien, ChatKit juga membutuhkan mitra server untuk membuat dan mengelola pengguna dengan aman:

Kami tidak akan mengotentikasi pengguna dalam tutorial ini, tetapi kami masih perlu mendefinisikan rute yang, ketika dipanggil, menciptakan pengguna ChatKit.
Mulailah dengan menginstal @pusher/chatkit-server :
npm install --save @pusher/chatkit-server
Kemudian perbarui ./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}`)
}
})Ingatlah untuk mengganti "Locator Instance Anda" dan "kunci Anda" dengan nilai masing -masing.
Ada banyak hal untuk dibongkar di sini, mulai dari atas:
Chatkit dari @pusher/chatkit-serverchatkit kami sendiri menggunakan instance locator dan kunci yang kami catat pada langkah sebelumnya/users , kami mengambil username dan membuat pengguna ChatKit melalui instance chatkit kami/authenticate untuk mengotentikasi mereka. Server perlu merespons dengan token (dikembalikan oleh chatkit.authenticate ) jika permintaan tersebut valid. Dalam kasus kami, kami akan - dengan naif - asumsikan bahwa semua orang adalah siapa mereka mengatakannya, dan mengembalikan token dari chatkit.authenticate tidak peduli apa pun.Boom?! Hanya itu yang perlu kita lakukan di server. Mari kita beralih ke klien ...
Ketika seseorang memuat aplikasi, kami ingin bertanya kepada mereka siapa mereka.
Setelah mereka menekan kirim , kami akan mengirimkan nama pengguna mereka ke server (ke rute /users yang baru saja kami tentukan) dan membuat pengguna ChatKit jika tidak ada.
Untuk mengumpulkan nama pengguna, buat komponen yang disebut UsernameForm.js di ./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 Kemudian perbarui 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 Jalankan aplikasi menggunakan npm start dan Anda akan melihat bahwa layar diterjemahkan:

Mulai dari atas App.js :
UsernameForm . Mungkin terlihat akrab bagi Anda karena menggunakan pola reaksi umum yang disebut komponen terkontrol. Anda dapat membaca lebih lanjut tentang bentuk reaksi di sinirender , kami membuat UsernameForm dan menghubungkan event handler onUsernameSubmittedonUsernameSubmitted dipanggil, kami mengirim permintaan pos ke rute /users yang baru saja kami tentukan. Jika permintaan berhasil, kami memperbarui this.state.currentUsername sehingga kami dapat merujuknya nanti; Kalau tidak, kami console.error kesalahan Saat ini, kami membuat UsernameForm dan menempati seluruh layar (lihat tangkapan layar di atas).
Setelah nama pengguna telah dikirimkan, kami ingin beralih ke layar yang berbeda - yaitu, layar obrolan.
Untuk melakukan itu, pertama -tama kita perlu membuat komponen ChatScreen.js di ./src :
+ import React, { Component } from 'react'
+
+ class ChatScreen extends Component {
+ render() {
+ return (
+ <div>
+ <h1>Chat</h1>
+ </div>
+ )
+ }
+ }
+
+ export default ChatScreen Kemudian perbarui 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 Daripada menggunakan router, kami secara kondisional membuat layar berdasarkan this.state.currentScreen .
Sebelumnya, kami menginstal @pusher/chatkit-server . Sekarang kami berada di tanah klien, Anda harus menginstal @pusher/chatkit-client juga:
npm install --save @pusher/chatkit-client
Kemudian perbarui 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 ChatScreenIngatlah untuk mengganti "Locator Instance Anda" dengan milik Anda yang Anda catat sebelumnya.
Sekali lagi, mulai dari atas:
ChatkitChatManager kami dengan instanceLocator kami, userId (dari this.props.currentUsername ), dan TokenProvider khusus. TokenProvider menunjuk ke rute /authenticate yang kami definisikan sebelumnyaChatManager diinisialisasi, kami dapat menghubungi connect . connect terjadi secara tidak sinkron dan Promise dikembalikan. Jika Anda telah mengikuti langkah -langkah ini dengan tepat, Anda akan terhubung. Yang sedang dikatakan, waspadalah terhadap console.error apa pun. Saat menggunakan ChatKit, semua pesan dikirim ke ruang ChatKit.
Kamar dapat dibuat secara terprogram (di server atau klien menggunakan createRoom ), atau di Inspektur Dasbor.
Membuat kamar -kamar dari inspektur sebenarnya bukan praktik yang baik (ini terutama dimaksudkan untuk pengujian) tetapi untuk tujuan panduan ini, kita tetap akan melakukannya.
Di dasbor, buka tab Konsol , di mana Anda akan menemukan inspektur dan membuat pengguna dengan nama apa pun. Saya akan menyebut saya "admin" saya.
Kemudian, buat ruangan yang disebut "Jenderal":

Sangat penting untuk dicatat bahwa ID kamar unik yang disorot di atas.
Langkah ini menandai poin penting dalam walkthrough.
Sekarang kami memiliki boilerplate kami di tempat, kami dapat dengan cepat mulai membangun fitur obrolan.
Ke depan, kami akan memecah setiap fitur menjadi komponen bereaksi independen (dapat digunakan kembali, jika Anda mau!):

Kami akan membuat setiap komponen saat kami melanjutkan, tetapi untuk membuat tutorial sedikit lebih mudah untuk diikuti, mari atur tata letak UI komponen dasar sekarang:
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 ChatScreenJika Anda menjalankan aplikasi sekarang, Anda akan melihat tata letak dasar terjadi:

Luar biasa!
Saya sangat senang menunjukkan ini kepada Anda!
Sekarang kami memiliki koneksi Chatkit , membangun fitur obrolan menjadi sesederhana menghubungkan acara Chatkit ke komponen UI. Di sini, izinkan saya menunjukkan kepada Anda.
Pertama, buat komponen MessageList.js tanpa kewarganegaraan di ./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 Kemudian perbarui 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 ChatScreenIngatlah untuk mengganti ID kamar Anda dengan ID kamar Anda sendiri yang Anda catat sebelumnya.
Mari kita hancurkan:
currentUser yang mewakili pengguna yang terhubung saat inicurrentUsersubscribeToRoom di currentUser ( currentUser.subscribeToRoom )subscribeToRoom mengambil pawang acara yang disebut onMessage yang dipanggil secara real-time setiap kali pesan baru tibamessageLimit menjadi 100 , onMessage juga disebut retroaktif hingga 100 pesan terbaru. Dalam praktiknya, ini berarti jika Anda menyegarkan halaman, Anda akan melihat hingga 100 pesan obrolan terbaruKami sedang berguling!
Selanjutnya, mari kita izinkan pengguna untuk mengirim pesan dengan terlebih dahulu membuat komponen SendMessageForm.js di ./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 Kemudian - Anda dapat menebaknya - perbarui 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 Komponen SendMessageForm pada dasarnya sama dengan komponen WhatIsYourUsernameForm yang kami tetapkan sebelumnya.
Ketika SendMessageForm diajukan, kami mengakses this.state.currentUser dan hubungi sendMessage (ingat, sebagian besar interaksi terjadi pada currentUser )
Anda mungkin dapat melihat pola yang muncul ...
ChatScreen adalah komponen kontainer yang mengelola status aplikasi kami dan menjadikan UI menggunakan komponen presentasional - biasanya tanpa kewarganegaraan. Sebagian besar kode kami melibatkan menghubungkan acara ChatKit dan data terkaitnya untuk bereaksi komponen UI.
Jika Anda pernah mencoba menerapkan indikator pengetikan Anda sendiri, Anda akan tahu itu bisa rumit. Secara umum, lebih banyak fitur real-time berarti lebih banyak data dan lebih banyak koneksi untuk dikelola.
Dengan ChatKit, Anda dapat menambahkan indikator pengetikan dengan sedikit usaha.
Mulailah dengan membuat komponen TypingIndicator.js di ./src/components :
+ 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 Kemudian perbarui 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 ChatScreenSaat menggunakan ChatKit, indikator mengetik mendidih ke dua tindakan mendasar:
currentUser.userIsTyping Ketika pengguna saat ini mulai mengetik; Kemudian,userStartedTyping dan userStoppedTypingDan itu cukup banyak.
"Tapi Alex, bagaimana kalau pengguna berhenti mengetik?"
Itu pertanyaan yang sangat bagus.
Chatkit cerdas seperti itu. Jika Layanan tidak menerima acara userIsTyping setelah beberapa detik, itu mengasumsikan currentUser telah berhenti mengetik. Karena itu, tidak perlu secara manual menaikkan suatu acara ketika seseorang berhenti mengetik. Cukup apik, kan?
Bisakah Anda merasakan momentumnya? Hampir selesai sekarang?
Untuk menyelesaikan aplikasi obrolan, mari kita gunakan fitur "Who's Online" untuk membuat daftar pengguna dan status online real-time mereka.
Mulailah dengan membuat komponen WhosOnlineList.js di /src/components :
+ 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 Lalu - untuk terakhir kalinya? - Perbarui 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 Mengelola keadaan pengguna Anda dalam keadaan bereaksi bisa sedikit rumit sehingga kami mengelolanya untuk Anda di currentRoom.users .
Saat pengguna terhubung dan memutuskan sambungan, properti ini diperbarui secara dinamis. Dengan kata lain, currentRoom.users harus selalu memilih kembali keadaan aplikasi obrolan Anda saat ini.
Oleh karena itu, ketika pengguna datang online atau pergi offline ( onPresenceChange ), atau pengguna baru bergabung ( onUserAdded ) yang harus kami lakukan hanyalah panggilan forceUpdate yang memberi tahu bereaksi untuk mengevaluasi currentRoom.users dan memperbarui UI.
Sekali lagi, itu benar -benar bermuara pada kabel beberapa data dan peristiwa sederhana untuk bereaksi komponen dan itu saja, teman -teman!
Dalam walkthrough ini, Anda membuat aplikasi obrolan lengkap dengan
Karena kami menggunakan ChatKit, kami juga mendapatkan beberapa fitur bonus secara gratis:
Kami menulis cukup banyak kode, tetapi tidak ada yang rumit.
Chatkit memiliki API minimal namun kuat yang mengelola semua data obrolan kami untuk kami. Yang harus kami lakukan adalah mengambil data itu dan membuatnya untuk pengguna.
Ingin terus membangun? Mengapa tidak menambahkan dukungan media yang kaya dan membaca kwitansi? Chatkit mendukung keduanya:
Anda juga mungkin tertarik untuk memeriksa demo Chatkit Slack kami yang kuat (250+ bintang ️). Ini mirip dengan aplikasi yang baru saja kami bangun tetapi lebih lengkap.
Apa yang akan Anda bangun dengan Chatkit? Kami ingin melihat! Umpan balik Anda memandu kami dalam meningkatkan Chatkit. Beri tahu kami apa yang membantu Anda mencapai tujuan Anda, apa yang menghalangi Anda, atau apa yang hilang.