Implement react-hooks-sse library
This commit is contained in:
parent
4c77fb127d
commit
2977247193
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,7 +1,8 @@
|
|||||||
.env
|
.env
|
||||||
.overnodebundle
|
.overnodebundle
|
||||||
*.old
|
*.old
|
||||||
node/node_modules
|
backend/node_modules
|
||||||
|
frontend/node_modules
|
||||||
nginx-react/node_modules
|
nginx-react/node_modules
|
||||||
nginx-react/build
|
nginx-react/build
|
||||||
.vscode
|
.vscode
|
||||||
|
@ -10,7 +10,7 @@ const mongoUri = process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/default?rep
|
|||||||
// Minio set-up variables
|
// Minio set-up variables
|
||||||
const minioURI = new URL(process.env.MINIO_URI || 'http://kspace-mugshot:2mSI6HdbJ8@127.0.0.1:9000/kspace-mugshot');
|
const minioURI = new URL(process.env.MINIO_URI || 'http://kspace-mugshot:2mSI6HdbJ8@127.0.0.1:9000/kspace-mugshot');
|
||||||
const minioBucket = minioURI.pathname.substring(1);
|
const minioBucket = minioURI.pathname.substring(1);
|
||||||
const historyNumber = process.env.HISTORY_AMOUNT || 10;
|
const historyNumber = parseInt(process.env.HISTORY_AMOUNT) || 1000;
|
||||||
|
|
||||||
// Stream set-up variables
|
// Stream set-up variables
|
||||||
let changeStream;
|
let changeStream;
|
||||||
@ -28,16 +28,15 @@ async function run() {
|
|||||||
console.log('server.js has been launched');
|
console.log('server.js has been launched');
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
// Configuring mongoDB connection
|
|
||||||
await mongoClient.connect();
|
await mongoClient.connect();
|
||||||
const collection = mongoClient.db().collection(mongoCollection);
|
const collection = mongoClient.db().collection(mongoCollection);
|
||||||
|
|
||||||
let eventArray = [];
|
let eventArray = [];
|
||||||
|
|
||||||
// Opening event listener on the database
|
|
||||||
changeStream = collection.watch(pipeline, options);
|
changeStream = collection.watch(pipeline, options);
|
||||||
console.log("Started watching changes in database");
|
console.log("Started watching changes in database");
|
||||||
|
|
||||||
|
// Triggers on GET at /event route
|
||||||
app.get('/events', async function (request, response) {
|
app.get('/events', async function (request, response) {
|
||||||
let minioClient = new minio.Client({
|
let minioClient = new minio.Client({
|
||||||
endPoint: minioURI.hostname,
|
endPoint: minioURI.hostname,
|
||||||
@ -47,19 +46,24 @@ async function run() {
|
|||||||
secretKey: minioURI.password
|
secretKey: minioURI.password
|
||||||
});
|
});
|
||||||
|
|
||||||
// Setting the header to event-stream for Server Sent Events (Eventsource)
|
// Notify SSE to React
|
||||||
const header = { 'Content-Type': 'text/event-stream', 'Connection': 'keep-alive' };
|
const header = { 'Content-Type': 'text/event-stream', 'Connection': 'keep-alive' };
|
||||||
response.writeHead(200, "OK", header);
|
response.writeHead(200, "OK", header);
|
||||||
response.write('Connection established \n\n');
|
response.write('Connection established \n\n');
|
||||||
|
|
||||||
// Triggers callback on every change in collection set up
|
const historyCursor = collection.find({}).sort({$natural : -1}).limit(historyNumber);
|
||||||
|
|
||||||
|
historyCursor.forEach((document) => {
|
||||||
|
const stringFormat = JSON.stringify(document);
|
||||||
|
eventArray = [stringFormat, ...eventArray];
|
||||||
|
})
|
||||||
|
response.write(`event: events, data: [${[...eventArray]}]\n\n`)
|
||||||
|
|
||||||
changeStream.on("change", data => {
|
changeStream.on("change", data => {
|
||||||
|
|
||||||
// Retrieves modified document on the db and stores it
|
|
||||||
let document = JSON.stringify(data.fullDocument);
|
let document = JSON.stringify(data.fullDocument);
|
||||||
eventArray = [document];
|
eventArray = [document];
|
||||||
|
|
||||||
// Fetch screenshot if there is one
|
|
||||||
if (data.fullDocument.screenshot_count) {
|
if (data.fullDocument.screenshot_count) {
|
||||||
|
|
||||||
for (let i = 1; i <= data.fullDocument.screenshot_count ; i++) {
|
for (let i = 1; i <= data.fullDocument.screenshot_count ; i++) {
|
||||||
@ -72,8 +76,8 @@ async function run() {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// sends updated array
|
|
||||||
response.write(`data: [${[...eventArray]}]\n\n`);
|
response.write(`data: [${[...eventArray]}]\n\n`);
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ x-common: &common
|
|||||||
ME_CONFIG_MONGODB_AUTH_DATABASE: admin
|
ME_CONFIG_MONGODB_AUTH_DATABASE: admin
|
||||||
MONGO_URI: mongodb://127.0.0.1:27017/default?replicaSet=rs0
|
MONGO_URI: mongodb://127.0.0.1:27017/default?replicaSet=rs0
|
||||||
MONGO_COLLECTION: eventlog
|
MONGO_COLLECTION: eventlog
|
||||||
|
HISTORY_AMOUNT: 10
|
||||||
MINIO_ACCESS_KEY: kspace-mugshot
|
MINIO_ACCESS_KEY: kspace-mugshot
|
||||||
MINIO_SECRET_KEY: 2mSI6HdbJ8
|
MINIO_SECRET_KEY: 2mSI6HdbJ8
|
||||||
MINIO_DEFAULT_BUCKETS: kspace-mugshot:download
|
MINIO_DEFAULT_BUCKETS: kspace-mugshot:download
|
||||||
|
20
frontend/package-lock.json
generated
20
frontend/package-lock.json
generated
@ -13,6 +13,7 @@
|
|||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-hooks-sse": "^2.0.0",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
"web-vitals": "^2.1.3"
|
"web-vitals": "^2.1.3"
|
||||||
}
|
}
|
||||||
@ -12952,6 +12953,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",
|
||||||
"integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA=="
|
"integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/react-hooks-sse": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-hooks-sse/-/react-hooks-sse-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Bv/KYK+QUVS6UWwCyx6nyaOYIvaTMTCjmlXuBK9nATH2DOz+g4PGiIxi5q71ljUTmSPn/q9Cod7xwDA3/gqVQA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.1.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">= 16.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
@ -25025,6 +25037,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",
|
||||||
"integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA=="
|
"integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA=="
|
||||||
},
|
},
|
||||||
|
"react-hooks-sse": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-hooks-sse/-/react-hooks-sse-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Bv/KYK+QUVS6UWwCyx6nyaOYIvaTMTCjmlXuBK9nATH2DOz+g4PGiIxi5q71ljUTmSPn/q9Cod7xwDA3/gqVQA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.1.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-hooks-sse": "^2.0.0",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
"web-vitals": "^2.1.3"
|
"web-vitals": "^2.1.3"
|
||||||
},
|
},
|
||||||
|
@ -1,28 +1,29 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { useSSE, SSEProvider, createCustomSource } from 'react-hooks-sse';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import EventList from '../eventList/EventList.js';
|
import EventList from '../eventList/EventList.js';
|
||||||
|
|
||||||
function App(props) {
|
function SSE() {
|
||||||
const [events, setEvents] = useState(['EventLog']); // initialises Event state
|
const state = useSSE('events');
|
||||||
const [sse, setSse] = useState(new EventSource('/events', { withCredentials: true })) // creates eventSource listener in state
|
const [events, setEvents] = useState([]); // initialises Event state
|
||||||
|
|
||||||
sse.onerror = (e) => {
|
useEffect(() => {
|
||||||
console.error();
|
console.log('render');
|
||||||
sse.close();
|
if (state) {
|
||||||
|
setEvents([JSON.parse(state.data), ...events]);
|
||||||
|
}
|
||||||
|
}, [state])
|
||||||
|
|
||||||
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
sse.onmessage = (e) => {
|
function App() {
|
||||||
// parses received data from string to JSON
|
|
||||||
const message = JSON.parse(e.data);
|
|
||||||
|
|
||||||
// initialises a new array with updated server-side event array
|
return (
|
||||||
const newEvents = [...message, ...events];
|
<SSEProvider endpoint="/events">
|
||||||
|
<SSE/>
|
||||||
// sets the updated event array as state
|
</SSEProvider>
|
||||||
setEvents(newEvents);
|
)
|
||||||
};
|
|
||||||
|
|
||||||
return <EventList data={events} />
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,15 +3,13 @@ import Event from '../event/Event.js';
|
|||||||
import './EventList.css';
|
import './EventList.css';
|
||||||
|
|
||||||
function EventList(props) {
|
function EventList(props) {
|
||||||
console.log(`FROM LIST: ${props.data}`);
|
return ;
|
||||||
|
// <ul className="eventListUl">
|
||||||
|
// {props.data.map((event) => {
|
||||||
|
// return <li className="eventListLi"><Event data={event} /></li>
|
||||||
|
// })}
|
||||||
|
// </ul>
|
||||||
|
|
||||||
return (
|
|
||||||
<ul className="eventListUl">
|
|
||||||
{props.data.map((event) => {
|
|
||||||
return <li className="eventListLi"><Event data={event} /></li>
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user