skip to Main Content

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>
  );

};

3

Answers


  1. You can look into Web Sockets:

    https://developer.mozilla.org/en-US/docs/Web/API/WebSocket

    You can also look into applying a setInterval perhaps to "poll" for changes.

    Found this:
    How to setInterval for every 5 second render with React hook useEffect in React Native app?

    Note the clear interval part.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
  3. 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';
    
    // first you will need useInterval hook, you can implement it yourself or grab it from the lib. 
    export function useInterval(callback, delay) { 
      const savedCallback = useRef(); 
      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(allvisitor);
        } 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>
      );
    
    };
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search