Temporary solution: renderToStaticMarkup

This commit is contained in:
Zhongheng Liu 2023-12-21 19:07:06 +02:00
commit 6fc628aee3
No known key found for this signature in database
6 changed files with 118 additions and 58 deletions

20
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,20 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/src/Chat/Chat.tsx",
"outFiles": [
"${workspaceFolder}/**/*.js"
]
}
]
}

View file

@ -1,16 +1,17 @@
import React from "react"; import React, { useState } from "react";
import ChatWrapper from "./Chat/Chat"; import ChatWrapper from "./Chat/Chat";
const App = (): React.ReactElement => { const App = (): React.ReactElement => {
var username: string | null = prompt("Username: ") const [username, setUsername] = useState<string>()
if (!username) { if (!username) {
alert("Invalid username!") const newName = prompt("Username:") as string
var username: string | null = prompt("Username: ") setUsername(newName)
} }
return ( return (
<div className="App"> <div className="App">
<h1>Local Area Network Chat Application</h1> <h1>Local Area Network Chat Application</h1>
<pre>This web application was built for the purposes of an EPQ project.</pre> <pre>This web application was built for the purposes of an EPQ project.</pre>
<ChatWrapper user={username as string} brokerURL=""/>
{<ChatWrapper user={username as string} brokerURL=""/> }
</div> </div>
) )
} }

View file

@ -1,9 +1,11 @@
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import { Message } from "./Message"; import { Message } from "./Message";
import { Client, Stomp } from "@stomp/stompjs"; import { Client, Stomp } from "@stomp/stompjs";
import { MessageType } from "./types"; import { MessageType } from "./types";
import useWebSocket from "react-use-websocket"; import { renderToStaticMarkup } from 'react-dom/server';
const domain = "localhost"
const port = "8080"
const connectionAddress = `ws://${domain}:${port}/ws`
const ChatWrapper = ( const ChatWrapper = (
{ {
user, user,
@ -14,24 +16,23 @@ const ChatWrapper = (
brokerURL: string, brokerURL: string,
} }
): React.ReactElement => { ): React.ReactElement => {
const domain = "localhost"
const port = "8080"
const connectionAddress = `ws://${domain}:${port}/ws`
const stompClient = new Client({ const stompClient = new Client({
brokerURL: connectionAddress brokerURL: connectionAddress
}) })
const [destination, setDestination] = useState<string>("/app/chat") const destination = "/app/chat"
const [connected, setConnected] = useState(false) const subscribe = "/sub/chat"
const [subscribe, setSubscribe] = useState("/sub/chat") // const [children, setChildren] = useState<React.ReactElement[]>([])
const [username, setUsername] = useState<string>(user)
const [children, setChildren] = useState<React.ReactElement>()
stompClient.onConnect = (frame) => { stompClient.onConnect = (frame) => {
setConnected(true);
stompClient.subscribe(subscribe, (message) => { stompClient.subscribe(subscribe, (message) => {
console.log(`Collected new message: ${message.body}`); console.log(`Collected new message: ${message.body}`);
const {from, to, content} = JSON.parse(message.body) as MessageType const {from, to, content} = JSON.parse(message.body) as MessageType
const messageElement = <Message sender={from} text={content} /> const messageElement = <Message sender={from} text={content} />
setChildren(messageElement) // setChildren((prev) => [...prev, messageElement])
console.log(messageElement);
// Temporary solution
const container = document.getElementById("chat-inner") as HTMLDivElement
container.innerHTML += renderToStaticMarkup(messageElement)
}) })
} }
stompClient.onWebSocketError = (error) => { stompClient.onWebSocketError = (error) => {
@ -42,58 +43,37 @@ const ChatWrapper = (
console.error('Broker reported error: ' + frame.headers['message']); console.error('Broker reported error: ' + frame.headers['message']);
console.error('Additional details: ' + frame.body); console.error('Additional details: ' + frame.body);
}; };
const sendDataButtonHandler = (ev: React.MouseEvent) => { const sendDataButtonHandler = (ev: React.MouseEvent) => {
console.log("WebSockets handler invoked.") console.log("WebSockets handler invoked.")
ev.preventDefault()
const entryElement: HTMLInputElement = document.getElementById("data-entry") as HTMLInputElement const entryElement: HTMLInputElement = document.getElementById("data-entry") as HTMLInputElement
const messageData = const messageData =
{ {
from: username, from: user,
to: "everyone", to: "everyone",
content: entryElement.value content: entryElement.value
} }
console.log(`STOMP connection status: ${stompClient.connected}`); console.log(`STOMP connection status: ${stompClient.connected}`);
if (stompClient.connected) { stompClient.publish({
stompClient.publish({ body: JSON.stringify(messageData),
body: JSON.stringify(messageData), destination: destination
destination: destination })
}) ev.preventDefault()
} else {alert("STOMP not activated!")}
} }
const connect = () => { useEffect(() => {
stompClient.activate() stompClient.activate()
} return () => {
const disconnect = () => { stompClient.deactivate()
stompClient.deactivate() }
} }, [])
// connection.addEventListener("open", (ev: Event) => {
// ev.preventDefault()
// connection.send("Hello world!")
// })
// connection.addEventListener("message", (ev: MessageEvent) => {
// ev.preventDefault()
// const wrappers = document.getElementsByClassName(msgWrapperClassName)
// // Matches data from JSON data input against ChatMessage datatype for processing
// const data = JSON.parse(ev.data) as ChatMessage
// for (let index = 0; index < wrappers.length; index++) {
// const element: Element | null = wrappers.item(index);
// if (!element) {
// console.error("msgWrapper class cannot be found! Message not delivered.")
// return
// }
// messageElementsArray.push(<Message sender={data.from} text={data.message} />)
// // TODO Create new message
// // DDL 20 DEC
// }
// })
return ( return (
<div className="chat"> <div className="chat">
<button onClick={ev => connect()} disabled={false}>Connect</button> {/* <button onClick={ev => {connect()}} disabled={connected}>Connect</button>
<button onClick={ev => disconnect()} disabled={!connected}>Disconnect</button> <button onClick={ev => {disconnect()}} disabled={!connected}>Disconnect</button> */}
<div id="chat-inner"> <div id="chat-inner">
{children} {/* {children} */}
</div> </div>
<span><input id="data-entry"></input><button onClick={ev => sendDataButtonHandler(ev)}>Send</button></span> <span><input id="data-entry"></input><button onClick={ev => sendDataButtonHandler(ev)}>Send</button></span>
</div> </div>

View file

@ -9,5 +9,5 @@ export const Message = (
} }
): React.ReactElement<{ sender: string; text: string; }> => { ): React.ReactElement<{ sender: string; text: string; }> => {
return (<p>Message from {sender} @ {}: {text}</p>); return (<p>Message from {sender}: {text}</p>);
}; };

61
src/Chat/Socket.tsx Normal file
View file

@ -0,0 +1,61 @@
import { Client } from "@stomp/stompjs"
import { useState } from "react"
import { Message } from "./Message"
import { MessageType } from "./types"
const Socket = (
{
address,
user,
messageCallback,
}:
{
address: string,
user: string,
messageCallback: (element: JSX.Element) => {},
}
) => {
const stompClient = new Client({
brokerURL: address
})
const destination = "/app/chat"
const subscribe = "/sub/chat"
stompClient.onConnect = (frame) => {
stompClient.subscribe(subscribe, (message) => {
console.log(`Collected new message: ${message.body}`);
const {from, to, content} = JSON.parse(message.body) as MessageType
const messageElement = <Message sender={from} text={content} />
// return message to parent
messageCallback(messageElement)
})
}
stompClient.onWebSocketError = (error) => {
console.error('Error with websocket', error);
};
stompClient.onStompError = (frame) => {
console.error('Broker reported error: ' + frame.headers['message']);
console.error('Additional details: ' + frame.body);
};
const send = () => {
console.log("WebSockets handler invoked.")
const entryElement: HTMLInputElement = document.getElementById("data-entry") as HTMLInputElement
const messageData =
{
from: user,
to: "everyone",
content: entryElement.value
}
console.log(`STOMP connection status: ${stompClient.connected}`);
stompClient.publish({
body: JSON.stringify(messageData),
destination: destination
})
}
stompClient.activate()
return (<></>)
}
export default Socket;

View file

@ -7,7 +7,5 @@ const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement document.getElementById('root') as HTMLElement
); );
root.render( root.render(
<React.StrictMode>
<App /> <App />
</React.StrictMode>
); );