-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathApp.jsx
334 lines (307 loc) · 9.48 KB
/
App.jsx
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
import React, { useState } from "react";
import CssBaseline from "@mui/material/CssBaseline";
import {
StompSessionProvider,
useStompClient,
useSubscription,
withStompClient,
withSubscription,
} from "react-stomp-hooks";
import {
Accordion,
AccordionDetails,
AccordionSummary,
Box,
Button,
Card,
CardContent,
Checkbox,
Container,
FormControlLabel,
Grid,
TextField,
Typography,
} from "@mui/material";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
export function App() {
const [enabled, setEnabled] = useState(true);
return (
//Initialize Stomp connection, will use sockjs, as the protocol specified is https
//The Connection can be used by all child components via the hooks or hocs.
<StompSessionProvider
url={"https://stream.elite12.de/api/sock"}
//All options supported by @stomp/stompjs can be used here
debug={(str) => {
console.log(str);
}}
//The enabled prop can be used to enable/disable the connection. Defaults to true
enabled={enabled}
>
<CssBaseline />
<FormControlLabel
className="enable-checkbox"
control={
<Checkbox
checked={enabled}
onChange={(event) => setEnabled(event.target.checked)}
/>
}
label="Enabled"
/>
<Container>
<Card style={{ margin: "3em" }}>
<CardContent>
<Typography>
You can see the STOMP Messages send and received in the browser
console
</Typography>
<Typography>
Note that, because the components are unmounted when the accordion
is unexpanded, all subscriptions are removed when you close the
accordion. You can furthermore globally enable/disable the
connection using the checkbox in the bottom right.
</Typography>
</CardContent>
</Card>
<Showcase title={"Subscribing"}>
<Subscribing />
</Showcase>
<Showcase title={"Sending Messages"}>
<SendingMessages />
</Showcase>
<Showcase title={"Higher Order Components"}>
<HigherOrderComponents />
</Showcase>
<Showcase title={"Dynamic subscribing/unsubscribing"}>
<DynamicSubscription />
</Showcase>
<Showcase title={"Multiple Providers"}>
<MultipleProviders />
</Showcase>
</Container>
</StompSessionProvider>
);
}
export function Subscribing() {
const [lastMessage, setLastMessage] = useState("No message received yet");
//Subscribe to /topic/test, and use handler for all received messages
//Note that all subscriptions made through the library are automatically removed when their owning component gets unmounted.
//If the STOMP connection itself is lost they are however restored on reconnect.
//You can also supply an array as the first parameter, which will subscribe to all destinations in the array
useSubscription("/topic/test", (message) => setLastMessage(message.body));
return <Box>Last Message: {lastMessage}</Box>;
}
export function SendingMessages() {
const [input, setInput] = useState("");
const [lastMessage, setLastMessage] = useState("No message received yet");
//Get Instance of StompClient
//This is the StompCLient from @stomp/stompjs
//Note: This will be undefined if the client is currently not connected
const stompClient = useStompClient();
useSubscription("/user/queue/echoreply", (message) =>
setLastMessage(message.body),
);
const sendMessage = () => {
if (stompClient) {
//Send Message
stompClient.publish({
destination: "/app/echo",
body: "Echo " + input,
});
} else {
//Handle error
}
};
return (
<Grid container direction="row" spacing={3}>
<Grid item>
<Button variant={"contained"} onClick={sendMessage}>
Send Message
</Button>
</Grid>
<Grid item>
<TextField
variant="standard"
value={input}
onChange={(event) => setInput(event.target.value)}
/>
</Grid>
<Grid item>
<Typography variant={"body1"}>
Last Message received: {lastMessage}
</Typography>
</Grid>
</Grid>
);
}
export const HigherOrderComponents = withStompClient(
withSubscription(
class HOCDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
input: "",
lastMessage: "No message received yet",
};
this.handleChange = this.handleChange.bind(this);
this.sendMessage = this.sendMessage.bind(this);
this.onMessage = this.onMessage.bind(this);
}
//You have to specify an onMessage method for the withSubscription HOC.
onMessage(message) {
this.setState({
lastMessage: message.body,
});
}
sendMessage() {
//stompClient prop is injected in the withStompClient HOC
if (this.props.stompClient) {
this.props.stompClient.publish({
destination: "/app/echo",
body: "Echo " + this.state.input,
});
}
}
handleChange(event) {
this.setState({
input: event.target.value,
});
}
render() {
return (
<Grid container direction="row" spacing={3}>
<Grid item>
<Button variant={"contained"} onClick={this.sendMessage}>
Send Message
</Button>
</Grid>
<Grid item>
<TextField
variant="standard"
value={this.state.input}
onChange={this.handleChange}
/>
</Grid>
<Grid item>
<Typography variant={"body1"}>
Last Message received: {this.state.lastMessage}
</Typography>
</Grid>
</Grid>
);
}
},
"/user/queue/echoreply",
),
);
export function DynamicSubscription() {
const [lastMessage, setLastMessage] = useState("No message received yet");
const [subscribed, setSubscribed] = useState(false);
useSubscription(
//The value of the first parameter can be mutated to dynamically subscribe/unsubscribe from topics
subscribed ? ["/topic/test"] : [],
(message) => setLastMessage(message.body),
);
return (
<Box
sx={{ width: "100%", display: "flex", justifyContent: "space-between" }}
>
<Box>Last Message: {lastMessage}</Box>
<Box>
<Button onClick={() => setSubscribed(!subscribed)}>
{subscribed ? "Unsubscribe" : "Subscribe"}
</Button>
</Box>
</Box>
);
}
export function MultipleProviders() {
//To allow for multiple STOMP connections, you can nest StompSessionProviders and specify a name for each
//Each child component can then specify which provider to use, by passing the name prop to the hooks or HOCs
return (
<StompSessionProvider
url={"https://stream.elite12.de/api/sock"}
name={"nested-1"}
>
<StompSessionProvider
url={"https://stream.elite12.de/api/sock"}
name={"nested-2"}
>
<StompSessionProvider
url={"https://stream.elite12.de/api/sock"}
name={"nested-3"}
>
{/* An empty name, or a name of "default" will use the default provider */}
<MultipleProviderChild />
<MultipleProviderChild name={"nested-1"} />
<MultipleProviderChild name={"nested-2"} />
<MultipleProviderChild name={"nested-3"} />
</StompSessionProvider>
</StompSessionProvider>
</StompSessionProvider>
);
}
function MultipleProviderChild(props) {
//All hooks and HOCs can optionally be passed a name argument to specify which provider to use
const stompClient = useStompClient(props.name);
useSubscription(
"/user/queue/echoreply", //The destination to subscribe to
(message) => setLastMessage(message.body), //The handler for the message
undefined, //No custom headers
props.name, //Specify the provider to use
);
const [input, setInput] = useState("");
const [lastMessage, setLastMessage] = useState("No message received yet");
const sendMessage = () => {
if (stompClient) {
//Send Message
stompClient.publish({
destination: "/app/echo",
body: "Echo " + input,
});
}
};
return (
<>
<Typography variant="h6" mb={2}>
Provider Name: {props.name || "default"}
</Typography>
<Grid container direction="row" spacing={3} mb={5}>
<Grid item>
<Button variant={"contained"} onClick={sendMessage}>
Send Message
</Button>
</Grid>
<Grid item>
<TextField
variant="standard"
value={input}
onChange={(event) => setInput(event.target.value)}
/>
</Grid>
<Grid item>
<Typography variant={"body1"}>
Last Message received: {lastMessage}
</Typography>
</Grid>
</Grid>
</>
);
}
export function Showcase(props) {
return (
<Accordion
style={{ margin: "3em" }}
TransitionProps={{ unmountOnExit: true }}
>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography>{props.title}</Typography>
</AccordionSummary>
<AccordionDetails>{props.children}</AccordionDetails>
</Accordion>
);
}