Building a chat app with React.js and Chatkit

Learn React.js through building a real-world chat app

    :root {
        --main-color: #5ea3d0;
        --secondary-color: white;
        --main-text-color: #3e5869;
        --secondary-text-color: #b0c7d6;
        --send-message-form: #F5F5F5;
    }
    
    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
        font-family: system-ui;
        font-weight: 200;
    import React from 'react'
    import Chatkit from '@pusher/chatkit'
    import MessageList from './components/MessageList'
    import SendMessageForm from './components/SendMessageForm'
    import RoomList from './components/RoomList'
    import NewRoomForm from './components/NewRoomForm'
    
    import { tokenUrl, instanceLocator } from './config'
    
    class App extends React.Component {
        constructor() {
            super()
            this.state = {
                currentRoomId: null,
    const tokenUrl = "https://us1.pusherplatform.io/services/chatkit_token_provider/v1/af799227-05d3-4a5b-ae27-8e378f5683b1/token";
    const instanceLocator = "v1:us1:af799227-05d3-4a5b-ae27-8e378f5683b1";
    
    exports.tokenUrl = tokenUrl;
    exports.instanceLocator = instanceLocator;
    
    
    import React from 'react'
    
    const DUMMY_DATA = [
        {
            senderId: 'perborgen',
            text: 'Hey, how is it going?'
        },
        {
            senderId: 'janedoe',
            text: 'Great! How about you?'
        },
        {
            senderId: 'perborgen',
            text: 'Good to hear! I am great as well'
    import React from 'react'
    import MessageList from './components/MessageList'
    import SendMessageForm from './components/SendMessageForm'
    import RoomList from './components/RoomList'
    import NewRoomForm from './components/NewRoomForm'
    
    class App extends React.Component {
        render() {
            return (
                <div className="app">
                    <RoomList />
                    <MessageList />
                    <SendMessageForm />
                    <NewRoomForm />
    import React from 'react'
    import Chatkit from '@pusher/chatkit'
    import MessageList from './components/MessageList'
    import SendMessageForm from './components/SendMessageForm'
    import RoomList from './components/RoomList'
    import NewRoomForm from './components/NewRoomForm'
    
    import { tokenUrl, instanceLocator } from './config'
    
    class App extends React.Component {
        
        componentDidMount() {
            const chatManager = new Chatkit.ChatManager({
                instanceLocator,
    import React from 'react'
    
    class MessageList extends React.Component {
        render() {
            return (
                <div className="message-list">
                    {this.props.messages.map((message, index) => {
                        return (
                            <div key={index} className="message">
                                <div className="message-username">{message.sen
                                <div className="message-text">{message.text}&l
                            </div>
                        )
                    })}
    import React from 'react'
    
    function Message(props) {  
        return (
            <div className="message">
                <div className="message-username">{props.username}</div>
                <div className="message-text">{props.text}</div>
            </div>
        )
    }
    
    export default Message
    
    /* https://reactjs.org/docs/components-and-props.html */
    import React from 'react'
    
    class SendMessageForm extends React.Component {
        
        constructor() {
            super()
            this.state = {
                message: ''
            }
            this.handleChange = this.handleChange.bind(this)
            this.handleSubmit = this.handleSubmit.bind(this)
        }
        
        handleChange(e) {
    import React from 'react'
    
    class SendMessageForm extends React.Component {
        
        constructor() {
            super()
            this.state = {
                message: ''
            }
            this.handleChange = this.handleChange.bind(this)
            this.handleSubmit = this.handleSubmit.bind(this)
        }
        
        handleChange(e) {
    import React from 'react'
    
    class RoomList extends React.Component {
        render () {
            return (
                <div className="rooms-list">
                    <ul>
                    <h3>Your rooms:</h3>
                        {this.props.rooms.map(room => {
                            return (
                                <li key={room.id} className="!">
                                    <a href="#"># {room.name}</a>
                                </li>
                            )
    import React from 'react'
    import Chatkit from '@pusher/chatkit'
    import MessageList from './components/MessageList'
    import SendMessageForm from './components/SendMessageForm'
    import RoomList from './components/RoomList'
    import NewRoomForm from './components/NewRoomForm'
    
    import { tokenUrl, instanceLocator } from './config'
    
    class App extends React.Component {
        
        constructor() {
            super()
            this.state = {
    import React from 'react'
    
    class RoomList extends React.Component {
        render () {
            const orderedRooms = [...this.props.rooms].sort((a, b) => a.id - b.id)
            return (
                <div className="rooms-list">
                    <ul>
                    <h3>Your rooms:</h3>
                        {orderedRooms.map(room => {
                            const active = this.props.roomId === room.id ? "active" 
                            return (
                                <li key={room.id} className={"room " + active}>
                                    <a
    import React from 'react'
    import ReactDOM from 'react-dom'
    import Message from './Message'
    
    class MessageList extends React.Component {
        
        componentWillUpdate() {
            const node = ReactDOM.findDOMNode(this)
            this.shouldScrollToBottom = node.scrollTop + node.clientHeight + 100 >= node.scrollHeight
        }
        
        componentDidUpdate() {
            if (this.shouldScrollToBottom) {
                const node = ReactDOM.findDOMNode(this)
    import React from 'react'
    
    class SendMessageForm extends React.Component {
        
        constructor() {
            super()
            this.state = {
                message: ''
            }
            this.handleChange = this.handleChange.bind(this)
            this.handleSubmit = this.handleSubmit.bind(this)
        }
        
        handleChange(e) {
    /** swap out */
    const tokenUrl = "https://us1.pusherplatform.io/services/chatkit_token_provider/v1/af799227-05d3-4a5b-ae27-8e378f5683b1/token";
    
    /** swap out */
    const instanceLocator = "v1:us1:af799227-05d3-4a5b-ae27-8e378f5683b1";
    
    export { tokenUrl, instanceLocator }
    :root {
        --main-color: #5ea3d0;
        --secondary-color: white;
        --main-text-color: #3e5869;
        --secondary-text-color: #b0c7d6;
        --send-message-form: #F5F5F5;
    }
    
    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
        font-family: system-ui;
        font-weight: 200;
    /*:root {
        --main-color: #5ea3d0;
        --secondary-color: white;
        --main-text-color: #3e5869;
        --secondary-text-color: #b0c7d6;
        --send-message-form: #F5F5F5;
    }*/
    
    :root {
        --main-color: #fd9ab6;
        --secondary-color: #fff4e6;
        --main-text-color: #11d7d8;
        --secondary-text-color: pink;
        --send-message-form: white;
    import React from 'react'
    import Chatkit from '@pusher/chatkit'
    import MessageList from './components/MessageList'
    import SendMessageForm from './components/SendMessageForm'
    import RoomList from './components/RoomList'
    import NewRoomForm from './components/NewRoomForm'
    
    import { tokenUrl, instanceLocator } from './config'
    
    class App extends React.Component {
        
        constructor() {
            super()
            this.state = {
Per Harald Borgen2:366 months ago

Chat is eating the world and React is eating front-end development, so why not learn React through building a chat app?


That's exacly what this course will enable you to do: at the end of it you'll both have a solid understanding of React.js and your very own personalised chat application. The chat will be built using the Chatkit API, meaning you don't have worry about doing any back-end coding.

Course content

The course contains 19 screencasts in total. Several of these include challenges where you'll be encouraged to jump into the code and change it. But don't worry if you don't manage to solve them: the instructor Per Harald Borgen will show you the solutions as well.

The chat app you'll create contains handy features like multiple rooms, the ability to create new rooms, autoscrolling, and more. Towards the end, you'll also learn a little bit of CSS Grid and CSS Variables, as it'll help you modify the design so that'll become your very own personalised app.

React concepts covered:

  • Class components
  • Event handlers
  • Life-cycle methods
  • JSX
  • State and props
  • Inverse data flow
  • Functional components

Per Harald Borgen is the instructor behind the very popular CSS Grid, Flexbox and CSS Variables courses here at Scrimba, so you'll be in good hands. You can follow him on Twitter here.

What people are saying about Scrimba: