Búsqueda de sitios web

reactjs - hacer que el contador de visitantes en vivo cambie sin actualizar


Mi cliente quiere hacer un contador total de visitantes.

¿Es posible hacer que el contador total de visitantes aumente incluso cuando el usuario no refresca la página? De modo que los usuarios puedan ver el total de visitantes aumentando sin refrescar la página. ¿Qué debería agregar para que esto suceda? Por favor, explique detalladamente porque soy nuevo en TypeScript.

aquí está mi código

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

};

Respuesta #1

Existen varias estrategias sobre cómo puedes obtener un contador en vivo o casi en vivo:

  • Simplemente consulta tu API en el intervalo que elijas para obtener estadísticas actualizadas. Súper fácil de implementar.
  • Long polling, probablemente es lo segundo más sencillo de implementar, pero requiere modificaciones en el backend
  • Usar eventos del lado del servidor
  • Usa websockets a través de una biblioteca, por ejemplo socket.io o sockjs

Solo el primer método no requiere ninguna modificación en el backend, y muy probablemente sería suficiente en tu caso. Solo necesitas agregar un hook que te permita sondear repetidamente una API: useInterval

Así es como podría verse

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

};

Respuesta #2

La arquitectura cliente-servidor web se basa esencialmente en el principio de que solo los clientes inician solicitudes.

Por lo tanto, la solución principal para tener una actualización regular sin que el visitante necesite actuar manualmente cada vez, es lanzar nuevas solicitudes de manera programática en algún intervalo predeterminado.

Aquí en React puedes usar, por ejemplo, el hook useInterval de 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
);

Ahora hay formas más avanzadas de tener una conexión "en vivo" entre el cliente y el servidor que permiten escapar del esquema original de solicitud iniciada por el cliente, como WebSockets (como se menciona en la respuesta de David) y Eventos del Servidor, pero eso requeriría configurar el servidor en consecuencia.

Artículos relacionados