-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathApp.tsx
119 lines (106 loc) · 3.31 KB
/
App.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { useEffect, useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
interface EventData {
count: number;
time: number;
type?: string;
message?: string;
}
function App() {
const [count, setCount] = useState(0);
const [messages, setMessages] = useState<EventData[]>([]);
const [connected, setConnected] = useState<boolean>(false);
const [completed, setCompleted] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
// Create SSE connection
const eventSource = new EventSource('/api/sse');
// Connection opened
eventSource.onopen = () => {
setConnected(true);
setError(null);
};
// Event received
eventSource.onmessage = (event) => {
console.log('Received message:', event.data);
try {
const data = JSON.parse(event.data) as EventData;
if (data.message) {
console.log('Completion message received:', data.message);
setCompleted(true);
setConnected(false);
eventSource.close();
} else {
setMessages((prevMessages) => [...prevMessages, data]);
}
} catch (err) {
console.error('Error parsing SSE data:', err);
}
};
// Error handling
eventSource.onerror = (err) => {
console.error('SSE error:', err);
setConnected(false);
setError('Connection to server failed. Make sure the FastAPI server is running.');
eventSource.close();
};
// Cleanup on component unmount
return () => {
eventSource.close();
};
}, []);
return (
<>
<div>
<a href="https://vite.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React + SSE + FastAPI</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
<hr></hr>
<h2>SSE</h2>
<div className="status-indicator">
Connection Status:
<span className={connected ? 'connected' : completed ? 'completed' : 'disconnected'}>
{connected ? 'Connected' : completed ? 'Completed' : 'Disconnected'}
</span>
</div>
{error && <div className="error-message">{error}</div>}
<div className="message-container">
<h2>Real-time Updates:</h2>
{messages.length === 0 ? (
<p>Waiting for messages...</p>
) : (
<ul>
{messages.map((msg, index) => (
<li key={index}>
{msg.type === 'completion' ? (
<span className="completion-message">{msg.message}</span>
) : (
<>Count: {msg.count} | Time: {new Date(msg.time * 1000).toLocaleTimeString()}</>
)}
</li>
))}
</ul>
)}
</div>
</>
)
}
export default App