I am working on an app that needs to count the number of users that are viewing a webpage at the same time. To do that, I created a React component that is responsible for the page display, and every time when it loads it sends a request to the Node.JS backend whose sole purpose is to keep track of the amount of users. Every time the page loads, it sends the get request to Node to get the amount of users and displays it as a state, and every time the user leaves the page the event listener must send a post request to decrement the value of variable by one. This is what I have so far:
server.js (back-end)
//This is a small backend that keeps track of how many people are on each page.
const express = require('express')
const cors = require('cors')
const app = express()
const whiteList = ['http://localhost:3000', 'http://127.0.0.1:3000']
const corsOptions = {
origin: function (origin, callback) {
if (!origin || whiteList.indexOf(origin) !== -1)
callback(null, true)
else
callback(new Error("Not allowed by CORS"))
},
credentials: true,
}
app.use(cors(corsOptions))
let googleCounter = 0, discordCounter = 0, linuxCounter = 0
console.log(googleCounter, discordCounter, linuxCounter)
app.get("/google", (request, response) => {
console.log(googleCounter, discordCounter, linuxCounter)
console.log(`Google counter ${googleCounter} increased to ${googleCounter + 1}`)
googleCounter++
response.send(`Google Counter: ${googleCounter}`)
})
app.get("/discord", (request, response) => {
discordCounter++
response.send(discordCounter)
})
app.get("/linux", (request, response) => {
linuxCounter++
response.send(linuxCounter)
})
//These methods will fire when users leave the pages.
app.post("/google", () => {
console.log(`Google counter ${googleCounter} decreased to ${googleCounter - 1}`)
googleCounter--})
app.post("/discord", () => discordCounter--)
app.post("/linux", () => linuxCounter--)
app.listen(5000, () => console.log(`Server started on port 5000: ${googleCounter}, ${discordCounter}, ${linuxCounter}`))
Google.js (the front-end)
//This is a generic page to view. Source: https://uk.wikipedia.org/wiki/Google
import React, {useState, useEffect} from "react"
import Base from "./Base"
export default function Google(props) {
const url = "http://localhost:5000/google"
const [counter, setCounter] = useState(1)
//Increment user counter when the page is loaded:
useEffect(() => {
if (!props.user) return;
fetch(url, {method: "GET"})
.then(response => {return response.text()})
.then(response => console.log(response))
.catch(error => console.log(error))
//Decrement user counter when the user leaves the page:
window.addEventListener("unload", () => fetch(url, {method: "POST"})
.then(response => {return response.text()})
.then(response => console.log(response))
.then(() => console.log("User left the page")))
.catch(error => console.log(error))
}, [props.user])
if (!props.user) return (<div><Base/></div>)
return (<div>
<h1>Google</h1>
<h2>Currently active users: {counter}</h2>
</div>)
}
My issue is that the googleCounter
variable behaves unpredictably: when I run the server, it immediately falls to -3 to -5, and every time I send the get request it increments the variable but also decrements. I suspect the unload
event could run more often than when user leaves the page, useEffect
could have run more often or the get request could overlap with the post request in some way. When I tried to log the post request from the client-side, I've got the event listener is undefined:
How can I make sure that the googleCounter
variable only decreases when the user leaves the page?