W
Wasp2w ago
G35x

How can I implement "live" UI updates based server-side results.

I have a setup in my WASP project where a user clicks a button, and my app sends data from the WASP server to a separate Node endpoint. Each request includes a JobID (representing the batch) and multiple subtaskIDs (mapped to individual database entities). I’ve set up a webhook in my WASP app to receive results from the Node server. The webhook invokes various server actions to updates the DB accordingly and tracks the status of the JobID and each subtaskID. Now, I want certain components in the UI (the ones initiating the batch) to subscribe to these updates, ideally in realtime so that I can reflect the status/result of each subtaskID as it completes, without needing to refresh or rerender the entire page. Re-rendering the entire page after a set amt of time is how it currently works, but this isn't sufficient because there are too many variables to reliably calculate how long a job will take like batch size, network latency, error handling/retries etc What’s the best way to implement realtime, secure server to client communication in WASP? Should I be looking into WebSockets, polling, or does WASP have a built in pattern for this kind of reactive update? Any guidance or examples would be much appreciated!
6 Replies
kapa.ai
kapa.ai2w ago
Hi @G35x. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the knowledge sources, the best approach for implementing real-time UI updates in your Wasp application would be to use WebSockets. Wasp provides built-in support for WebSockets through Socket.IO, which is ideal for your use case where you need server-to-client communication to update UI components when your webhook receives results. Using WebSockets in Wasp Wasp has integrated WebSocket support that you can implement in three steps: 1. Enable WebSockets in your Wasp file:
app yourAppName {
// ...

webSocket: {
fn: import { webSocketFn } from "@src/webSocket",
autoConnect: true, // optional, default: true
},
}
app yourAppName {
// ...

webSocket: {
fn: import { webSocketFn } from "@src/webSocket",
autoConnect: true, // optional, default: true
},
}
2. Define your WebSocket logic on the server by implementing the webSocketFn function that handles events and connections. 3. Use WebSockets on the client with the provided useSocket and useSocketListener hooks in your React components. Wasp WebSockets Documentation provides a complete guide on setting this up. Implementation Strategy For your specific use case: 1. When your webhook receives results from the Node server and updates the database, you can emit WebSocket events to connected clients with the updated status information. 2. Your UI components can listen for these events and update accordingly without refreshing the entire page. A current workaround (as mentioned in one of the GitHub issues) is to: - Create a global function in your webSocketFn - Export this function (e.g., ioInstance) - Import it in your webhook handler to send messages to connected clients
// In your webSocketFn
export let ioInstance;

export const webSocketFn = (io, context) => {
ioInstance = io;

io.on('connection', (socket) => {
// Handle connections
});
};
// In your webhook handler
import { ioInstance } from '@src/webSocket';

// Your webhook action
export const handleWebhookResult = async (args, context) => {
// Update database
// ...

// Emit event to clients
ioInstance.emit('job-update', {
jobId: args.jobId,
subtaskId: args.subtaskId,
status: args.status
});
};
// In your webSocketFn
export let ioInstance;

export const webSocketFn = (io, context) => {
ioInstance = io;

io.on('connection', (socket) => {
// Handle connections
});
};
// In your webhook handler
import { ioInstance } from '@src/webSocket';

// Your webhook action
export const handleWebhookResult = async (args, context) => {
// Update database
// ...

// Emit event to clients
ioInstance.emit('job-update', {
jobId: args.jobId,
subtaskId: args.subtaskId,
status: args.status
});
};
Alternative Approaches While WebSockets are the recommended approach for real-time updates, there are other options: 1. Automatic Query Invalidation: Wasp automatically invalidates queries when related entities are modified through actions. However, this might not be sufficient for your use case since it doesn't provide real-time updates from server to client without client interaction. 2. Polling: You could implement polling as a fallback, but it's less efficient than WebSockets for real-time updates. The Wasp team is also working on better support for real-time data updates as mentioned in GitHub issue #1454, but WebSockets are currently the most robust solution available in Wasp for your requirements. I hope this helps with your implementation! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @G35x, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
G35x
G35xOP2w ago
@kapa.ai thanks, would websockets work for "Streaming" data between client & server, like a chat session, for example?
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Yes, WebSockets in Wasp are perfect for streaming data between client and server in real-time applications like chat sessions. Wasp's WebSocket implementation (built on Socket.IO) is specifically designed for these types of use cases. The documentation actually provides a chat example to demonstrate this exact scenario:
// On the server side
export const webSocketFn = (io, context) => {
io.on('connection', (socket) => {
const username = getFirstProviderUserId(socket.data.user) ?? '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 })
})
})
}
// On the server side
export const webSocketFn = (io, context) => {
io.on('connection', (socket) => {
const username = getFirstProviderUserId(socket.data.user) ?? '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 })
})
})
}
On the client side, you can use the provided hooks to listen for and send messages:
// In your React component
const { socket, isConnected } = useSocket()

useSocketListener('chatMessage', logMessage)

function handleSubmit(e) {
e.preventDefault()
socket.emit('chatMessage', messageText)
setMessageText('')
}
// In your React component
const { socket, isConnected } = useSocket()

useSocketListener('chatMessage', logMessage)

function handleSubmit(e) {
e.preventDefault()
socket.emit('chatMessage', messageText)
setMessageText('')
}
This setup allows for: - Immediate message delivery - Real-time updates to all connected clients - Persistent connections that are more efficient than polling - Authentication integration (note the socket.data.user in the server example) Wasp WebSockets Documentation provides complete examples and API references for implementing this functionality. For TypeScript users, Wasp also offers full-stack type safety for your WebSocket events and payloads, making the development experience even better. Would you like more specific details about implementing a streaming chat application with Wasp? ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @G35x, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
miho
miho2w ago
@G35x did you get a good answer from the bot? 🙂
miho
miho2w ago
We have an issue open for this kind of feature, but for now - cooking it yourself with Websockets would be a good way to go: https://github.com/wasp-lang/wasp/issues/1454
GitHub
Adding support for real-time data updates · Issue #1454 · wasp-la...
Let's just see what we have now: 🟢 one user has a list of tasks open 🟠 another user creates a task 🟢 the first user won't get the update until they refresh the page This is fine for most us...
G35x
G35xOP2w ago
I think so! Haven't tested it out yet or begun implementing, but it gave me a clear direction to work in. Will report back if it worked 🙂

Did you find this page helpful?