My client want to make total visitor counter.
Is it possible to make the total visitor counter increase but when the user not refresh the page? so the users can see the total visitor increasing without refresh the page. What should i add to make it happen? Please kindly explain in detail because i am new to typescript.
here's my code
type visitortype={
count: number;
}
const Footer = () => {
const [visitor, setvisitor] = useState<visitortype>();
useEffect(() => {
fetch('https://count.cab/hit/ghG6Oirn0b')
.then(response => response.json())
.then(allvisitor=> setvisitor(allvisitor))
.catch(error => console.log(error));
}, []);
return (
<GridItem
w="100%"
h={{ base: "80px", lg: "300px" }}
colSpan={{ base: 8, lg: 4 }}
>
<VStack
align={{ base: "center", lg: "stretch" }}
marginTop={{ base: "0", lg: "60px" }}
marginLeft={{ base: "0", lg: "50px" }}
>
<Box w={{ base: "100px", lg: "220px" }} paddingBottom={"10px"}>
<Image src={imgLogoMd} alt="Logo" w="100%" />
<HStack>
<Text fontSize={{ base: "xs", lg: "md" }} textAlign={"justify"}>
{visitor?.count} Visitor
</Text>
</HStack>
</Box>
</VStack>
</GridItem>
);
};
There are several strategies how you can get live or close to live counter:
Only the first method not require any modifications on the backend, and most likely would be sufficient in your case. You just need to add a hook that will let you repeatedly poll an api: useInterval
Here is how it might look like
import {useEffect, useRef, useState} from 'react';
type CallbackType = (...args: any[]) => any;
// first you will need useInterval hook, you can implement it yourself or grab it from the lib.
export function useInterval(callback: CallbackType, delay: number) {
const savedCallback = useRef<CallbackType | undefined>();
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
useEffect(() => {
function func() {
savedCallback.current?.();
}
if (delay !== null) {
let id = setInterval(func, delay);
return () => clearInterval(id);
}
}, [delay]);
}
// let's say we would like to get fresh stats every minute
const REFRESH_INTERVAL = 60 * 1000
const Footer = () => {
const [visitor, setVisitor] = useState<visitortype>();
useInterval(async () => {
try {
const response = await fetch('https://count.cab/hit/ghG6Oirn0b')
const data = await response.json()
setVisitor(data);
} catch(error) {
console.log(error);
}
}, REFRESH_INTERVAL);
return (
<GridItem
w="100%"
h={{ base: "80px", lg: "300px" }}
colSpan={{ base: 8, lg: 4 }}
>
<VStack
align={{ base: "center", lg: "stretch" }}
marginTop={{ base: "0", lg: "60px" }}
marginLeft={{ base: "0", lg: "50px" }}
>
<Box w={{ base: "100px", lg: "220px" }} paddingBottom={"10px"}>
<Image src={imgLogoMd} alt="Logo" w="100%" />
<HStack>
<Text fontSize={{ base: "xs", lg: "md" }} textAlign={"justify"}>
{visitor?.count} Visitor
</Text>
</HStack>
</Box>
</VStack>
</GridItem>
);
};
The web client-server architecture is essentially based on the principle that only clients initiate requests.
Therefore the main solution to have a regular update without needing the visitor to manually take action every time, is to programmatically launch new requests at some pre-determined interval.
Here in React you can use e.g. useInterval hook from react-use:
import { useInterval } from 'react-use';
useInterval(
() => {
fetch('https://count.cab/hit/ghG6Oirn0b')
.then(response => response.json())
.then(allvisitor=> setvisitor(allvisitor))
.catch(error => console.log(error));
},
10_000 // Delay in milliseconds, e.g. here every 10 seconds
);
There are now more advanced ways to have a "live" connection between client and server that enable escaping from the original client-initiated request only scheme, like WebSockets (as mentionned in David's answer) and Server Events, but that would require to configure the server accordingly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With