Real Time Web dengan Express dan React Js

Asrul Harahap

Asrul Harahap

React Developer

Postingan ini dibuat untuk materi sharing session di Flock Company.

Ada banyak cara untuk membuat aplikasi yang realtime seperti firebase database, websocket, pusher, dll. Pada kali ini saya akan membahas web socket.

Web Socket

Server

Pada sisi server (nodejs), kita membutuhkan beberapa library yaitu:

  • express
  • cors
  • socket.io

Folder proyek ini dengan saya beri nama appsocket. Setelah folder dibuat arahkan terminal ke folder tersebut dengan cara:

cd ~/Desktop/appsocket

Folder proyek saya berada di Desktop, jika berbeda dengan saya silahkan disesuaikan. Jika sudah diarahkan pada terminal, selanjutnya lakukan inisial proyek node js dengan perintah berikut.

npm init

Proses ini dilakukan untuk membuat sebuah file package.json yang berguna untuk mengontrol proyek node js. Berikut isi file package.json yang dihasilkan.

{
"name": "appsocket",
"version": "1.0.0",
"description": "belajar expres bersama asrul.dev",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Asrul harahap",
"license": "ISC"
}

Install express dan beberapa dependensi lainnya dengan perintah berikut:

npm i express
npm i cors
npm i socket.io

Setelah diinstall kita dapat melihat perubahan pada file package.json menjadi seperti berikut.

{
"name": "appsocket",
"version": "1.0.0",
"description": "belajar expres bersama asrul.dev",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Asrul harahap",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.1",
"socket.io": "^2.3.0"
}
}

Buatlah file index.js dalam folder proyek yang telah kita buat sebelumnya dengan kode berikut.

const express = require("express")
const app = express()
const server = require("http").createServer(app)
const socket = require("socket.io")
const io = socket(server)
const cors = require('cors')
const port = 8080 || process.env.PORT;
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({extended: true}))
let data = []
app.all('/', (req, res) => {
const topic = "asrul-dev"
let pesan = req.body.pesan
let ip = req.connection.remoteAddress
let waktu = new Date()
data.push({pesan, ip, waktu})
io.emit(topic, data)
res.json("JALAN DONG....")
})
server.listen(port, console.log('running'))

Jalankan server dengan perintah berikut.

node index.js

Anda juga bisa membaca materi express di sini

Client

Pada Aplikasi client yang menggunakan react js, agar lebih cepat dalam instalasi silahkan gunakan CRA (create-react-app) saja.

Install CRA dengan perintah berikut.

npx create-react-app reactsocket

Kemudian install library socket untuk client dan axios untuk http request dengan cara berikut.

npm i socket.io-client
npm i axios

Buatlah file custom hooks untuk socket io, dengan nama useSocket.js yang isi kodenya seperti berikut.

import React, { useEffect, useState } from "react"
import socket from "socket.io-client"
const useSocket = (serverUrl, topic) => {
const [msg, setMsg] = React.useState(null)
const [isConnected, setConnected] = useState(false)
const client = socket.connect(serverUrl)
client.on("connect", () => setConnected(true))
client.on("disconnect", () => setConnected(false))
useEffect(() => {
client.on(topic, data => {
setMsg(data)
})
}, [topic, client])
return { msg, isConnected }
}
export default useSocket

Kemudian buatlah file dengan nama Socket.js yang isinya seperti berikut.

import React, { useState, Fragment } from "react";
import PropTypes from "prop-types";
import useSocket from "./useSocket";
import Axios from "axios";
const Sockt = ({ serverUrl, topic }) => {
const { msg, isConnected } = useSocket(serverUrl, topic)
const [pesan, setPesan] = useState('')
const sendMessage = e => {
e.preventDefault()
if(pesan.trim() !== '') {
Axios.post('http://localhost:8080', {pesan})
}
window.scrollTo(0,document.body.scrollHeight)
setPesan('')
}
return (
<Fragment>
<h2>You are {isConnected ? 'online' : 'offline'}</h2>
{msg !== null && msg.map( (item, index) => (
<div className="container" key={index}>
<img src="https://avatars.io/twitter/asruldev" alt="Avatar" style={{width:'100%'}} />
<p> {item.pesan} </p>
<span className="time-right">{ item.waktu } - by { item.ip }</span>
</div>
))}
<form className="stycky-bottom" onSubmit={e => sendMessage(e)}>
<input type="text" onChange={e => setPesan(e.target.value)} />
<button onClick={e => sendMessage(e)}>Send</button>
</form>
</Fragment>
);
};
Sockt.propTypes = {
serverUrl: PropTypes.string.isRequired,
topic: PropTypes.string.isRequired
};
export default Sockt;

File App.js yang isinya seperti berikut.

import React from 'react';
import './App.css'
import Sockt from "./Socket";
function App() {
return (
<div className="App">
<Sockt
serverUrl="http://localhost:8080/"
topic="asrul-dev"
/>
</div>
);
}
export default App;

Tambahan file App.css isinya seperti berikut.

body {
margin: 40px auto;
max-width: 800px;
padding: 40px;
}
.container {
border: 2px solid #dedede;
background-color: #f1f1f1;
border-radius: 5px;
padding: 10px;
margin: 10px 0;
}
.darker {
border-color: #ccc;
background-color: #ddd;
}
.container::after {
content: "";
clear: both;
display: table;
}
.container img {
float: left;
max-width: 60px;
width: 100%;
margin-right: 20px;
border-radius: 50%;
}
.container img.right {
float: right;
margin-left: 20px;
margin-right:0;
}
.time-right {
float: right;
color: #aaa;
}
.time-left {
float: left;
color: #999;
}
.stycky-bottom {
height: 30px;
background: gray;
width: 100%;
position: sticky;
bottom: 30px;
}
input {
width: 88%;
height: 30px;
}
button {
width: 10%;
height: 30px;
}

Sehingga Hasilnya akan seperti berikut.

Hasil Web Socket