Skip to main content
Version: 0.11.8

Web Sockets

Wasp provides a fully integrated WebSocket experience by utilizing Socket.IO on the client and server.

We handle making sure your URLs are correctly setup, CORS is enabled, and provide a useful useSocket and useSocketListener abstractions for use in React components.

To get started, you need to:

  1. Define your WebSocket logic on the server.
  2. Enable WebSockets in your Wasp file, and connect it with your server logic.
  3. Use WebSockets on the client, in React, via useSocket and useSocketListener.
  4. Optionally, type the WebSocket events and payloads for full-stack type safety.

Let's go through setting up WebSockets step by step, starting with enabling WebSockets in your Wasp file.

Turn On WebSockets in Your Wasp File

We specify that we are using WebSockets by adding webSocket to our app and providing the required fn. You can optionally change the auto-connect behavior.

todoApp.wasp
app todoApp {
// ...

webSocket: {
fn: import { webSocketFn } from "@server/webSocket.js",
autoConnect: true, // optional, default: true
},
}

Defining the Events Handler

Let's define the WebSockets server with all of the events and handler functions.

webSocketFn Function

On the server, you will get Socket.IO io: Server argument and context for your WebSocket function. The context object give you access to all of the entities from your Wasp app.

You can use this io object to register callbacks for all the regular Socket.IO events. Also, if a user is logged in, you will have a socket.data.user on the server.

This is how we can define our webSocketFn function:

src/server/webSocket.js
import { v4 as uuidv4 } from 'uuid'

export const webSocketFn = (io, context) => {
io.on('connection', (socket) => {
const username = socket.data.user?.email || socket.data.user?.username || 'unknown'
console.log('a user connected: ', username)

socket.on('chatMessage', async (msg) => {
console.log('message: ', msg)
io.emit('chatMessage', { id: uuidv4(), username, text: msg })
// You can also use your entities here:
// await context.entities.SomeEntity.create({ someField: msg })
})
})
}

Using the WebSocket On The Client

useSocket Hook

Client access to WebSockets is provided by the useSocket hook. It returns:

  • socket: Socket for sending and receiving events.
  • isConnected: boolean for showing a display of the Socket.IO connection status.
    • Note: Wasp automatically connects and establishes a WebSocket connection from the client to the server by default, so you do not need to explicitly socket.connect() or socket.disconnect().
    • If you set autoConnect: false in your Wasp file, then you should call these as needed.

All components using useSocket share the same underlying socket.

useSocketListener Hook

Additionally, there is a useSocketListener: (event, callback) => void hook which is used for registering event handlers. It takes care of unregistering the handler on unmount.

src/client/ChatPage.jsx
import React, { useState } from 'react'
import {
useSocket,
useSocketListener,
} from '@wasp/webSocket'

export const ChatPage = () => {
const [messageText, setMessageText] = useState('')
const [messages, setMessages] = useState([])
const { socket, isConnected } = useSocket()

useSocketListener('chatMessage', logMessage)

function logMessage(msg) {
setMessages((priorMessages) => [msg, ...priorMessages])
}

function handleSubmit(e) {
e.preventDefault()
socket.emit('chatMessage', messageText)
setMessageText('')
}

const messageList = messages.map((msg) => (
<li key={msg.id}>
<em>{msg.username}</em>: {msg.text}
</li>
))
const connectionIcon = isConnected ? '🟢' : '🔴'

return (
<>
<h2>Chat {connectionIcon}</h2>
<div>
<form onSubmit={handleSubmit}>
<div>
<div>
<input
type="text"
value={messageText}
onChange={(e) => setMessageText(e.target.value)}
/>
</div>
<div>
<button type="submit">Submit</button>
</div>
</div>
</form>
<ul>{messageList}</ul>
</div>
</>
)
}

API Reference

todoApp.wasp
app todoApp {
// ...

webSocket: {
fn: import { webSocketFn } from "@server/webSocket.js",
autoConnect: true, // optional, default: true
},
}

The webSocket dict has the following fields:

  • fn: WebSocketFn required

    The function that defines the WebSocket events and handlers.

  • autoConnect: bool

    Whether to automatically connect to the WebSocket server. Default: true.