Skip to content

Commit

Permalink
chore: add websockets example to nextjs playground (#1605)
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldambra authored Dec 16, 2024
1 parent 1fc5f2c commit 6f9e089
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 1 deletion.
2 changes: 2 additions & 0 deletions playground/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
"posthog-js": "1.200.1",
"react": "18.3.1",
"react-dom": "18.3.1",
"socket.io": "^4.8.1",
"socket.io-client": "^4.8.1",
"typescript": "4.9.5"
},
"devDependencies": {
Expand Down
7 changes: 7 additions & 0 deletions playground/nextjs/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ export default function App({ Component, pageProps }: AppProps) {
}
}, [])

useEffect(() => {
// make sure we initialize the WebSocket server
// we don't need to support IE11 here
// eslint-disable-next-line compat/compat
fetch('/api/socket')
}, [])

const localhostDomain = process.env.NEXT_PUBLIC_CROSSDOMAIN
? 'https://localhost:8000'
: process.env.NEXT_PUBLIC_POSTHOG_HOST
Expand Down
39 changes: 39 additions & 0 deletions playground/nextjs/pages/api/socket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Server } from 'socket.io'
import type { NextApiRequest, NextApiResponse } from 'next'
import type { Server as HttpServer } from 'http'
import type { Socket as NetSocket } from 'net'

// Extend the response object to include the custom `io` property
interface CustomServer extends HttpServer {
io?: Server
}

interface CustomNetSocket extends NetSocket {
server: CustomServer
}

interface CustomNextApiResponse extends NextApiResponse {
socket: CustomNetSocket
}

export default function handler(req: NextApiRequest, res: CustomNextApiResponse) {
if (!res.socket.server.io) {
const io = new Server(res.socket.server)
res.socket.server.io = io

io.on('connection', (socket) => {
// eslint-disable-next-line no-console
console.log('User connected', socket.id)

socket.on('send chat message', (msg) => {
socket.emit('message', msg)
})

socket.on('disconnect', () => {
// eslint-disable-next-line no-console
console.log('User disconnected', socket.id)
})
})
}
res.end()
}
68 changes: 68 additions & 0 deletions playground/nextjs/pages/chat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useState, useEffect } from 'react'
import io, { Socket } from 'socket.io-client'
import { DefaultEventsMap } from 'socket.io'

const Chat = () => {
// State to store the messages
const [messages, setMessages] = useState<any[]>([])
// State to store the current message
const [currentMessage, setCurrentMessage] = useState('')
const [socket, setSocket] = useState<Socket<DefaultEventsMap, DefaultEventsMap> | null>(null)

useEffect(() => {
// Create a socket connection
const createdSocket = io()

// Listen for incoming messages
createdSocket.on('message', (message) => {
setMessages((prevMessages) => [...prevMessages, message])
})

setSocket(createdSocket)

// Clean up the socket connection on unmount
return () => {
createdSocket.disconnect()
}
}, [])

const sendMessage = () => {
if (!socket) {
// eslint-disable-next-line no-console
console.log('socket not running, ruh roh!')
return
}

socket.emit('send chat message', currentMessage)
setCurrentMessage('')
}

return (
<div className={'w-full min-h-96 flex-col space-y-2'}>
<div className="flex flex-row justify-between items-center border border-gray-300 rounded p-2 space-x-2">
<input
className={'flex-1 border rounded px-2 py-1'}
type="text"
value={currentMessage}
onChange={(e) => setCurrentMessage(e.target.value)}
/>

<button onClick={sendMessage}>Send</button>
</div>

<div className="flex flex-col border rounded px-2 py-1">
{messages?.length === 0 && <p>No messages yet</p>}
{/* Display the messages */}
{messages
.filter((m) => !!m.trim().length)
.map((message, index) => (
<p className={'w-full border rounded px-2 py-1'} key={index}>
{message}
</p>
))}
</div>
</div>
)
}

export default Chat
3 changes: 3 additions & 0 deletions playground/nextjs/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export default function Home() {
<a className="Button" data-attr="autocapture-button" href="#">
<span>Autocapture a &gt; span</span>
</a>
<a className="Button" data-attr="chat-button" href="/chat">
<span>REAL TIME CHAT OMG</span>
</a>
<button
onClick={() => {
console.log(posthog.persistence?.props[STORED_PERSON_PROPERTIES_KEY])
Expand Down
Loading

0 comments on commit 6f9e089

Please sign in to comment.