Search code examples
javascriptreactjstypescript

Style for visitor counter React.js


I want to create visitor counter for my website. I use api to get hit counter. I want to create something like this

enter image description here

I try with code below but the result like this

enter image description here

I want to ask what I need to do to make it like the design I want. what code that I did wrong?

function Card(props:any) {
  const count = `${props.number}`.split('');
 
  return (
    <div style={{ display: "flex" }}>
      {count.map((val) => (
        <div
          style={{
            fontSize: 42,
            marginRight: 10,
            background: "#8D0000",
            color: "white",
            width: 40,
            height: 55,
            fontWeight: "bold",
            textAlign: "center"
          }}
        >
          {val}
        </div>
      ))}
    </div>
  );
}

const Footer = () => {
  const [visitor, setvisitor] = useState<visitortype>();

  useEffect(() => {
    fetch('https://count.cab/hit/ghG6Oirn0b')
    .then(response => response.json())
    .then(allvisitor=>  console.log(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" }}
      >
       <Card number={visitor?.count}/>

      </VStack>
    </GridItem>
  );
};




I also try using react-flip-number but still not like the style I want enter image description here

<FlipNumbers 
  height={25} 
  width={20}  
  color="white" 
  background="#8D0000"
  numberStyle={{
    fontSize: 16,
  }}
  play perspective={100} 
  numbers={`${visitor?.count ?? 0}`}
/>;

Solution

  • Reflection to your question

    The error, I believe, stems from a misunderstanding of how component parameter passing works. You thought that simply declaring the parameter passed to the component is sufficient. It's not. The component receives an object containing all the passed properties, including the one named "value" in your case. So, if you continue this way, you'll find it a bit awkward to access the value parameter from the object using value.value.

    <Card value={577} />
    
    // Now "value" is a object, what stored a properties (as "value={577}" attribute)
    const Card = (value) => {
      // Now can get "value" attribute from "value" object - not readable
      console.log(value.value) // 577
    }
    

    Solution

    In React.js, components receive passed variables as an object. You can either declare the object directly (e.g., as props) and reference its parameters later, or declare the parameters directly as shown in the second example.

    <Card number={577} anotherProp={true} />
    
    function Card(props) {
      // Can use properties as parameter of props object
      console.log(props.number) // 577
      console.log(props.anotherProp) // true
    }
    
    // or
    
    function Card({ number, anotherProp }) {
      // Can use properties when directly declared them in function
      // That's called "Destructuring assignment"
      console.log(number) // 577
      console.log(anotherProp) // true
    }
    

    More information

    Example

    // Import the React and ReactDOM modules
    const { useState, useEffect } = React;
    
    // The component receives the passed values as object (props)
    function Card(props) {
      const digits = `${props.number}`.split('');
     
      return (
        <div style={{ display: "flex" }}>
          {digits.map((val) => (
            <div
              style={{
                fontSize: 42,
                marginRight: 10,
                background: "#8D0000",
                color: "white",
                width: 40,
                height: 55,
                fontWeight: "bold",
                textAlign: "center"
              }}
            >
              {val}
            </div>
          ))}
        </div>
      );
    }
    
    // Instead of declaring the object (props), you can directly declare the parameters within { and }
    // That's called "Destructuring assignment"
    function AnotherCard({ number }) {
      const digits = `${number}`.split('');
     
      return (
        <div style={{ display: "flex" }}>
          {digits.map((val) => (
            <div
              style={{
                fontSize: 42,
                marginRight: 10,
                background: "#8D0000",
                color: "white",
                width: 40,
                height: 55,
                fontWeight: "bold",
                textAlign: "center"
              }}
            >
              {val}
            </div>
          ))}
        </div>
      );
    }
    
    // App component
    function App() {
      return (
        <div style={{ display: "grid", gap: "10px" }}>
          Example #1 (Card component with props object)
          <Card number={577} />
          
          Example #2 (AnotherCard component with destructuring assignment)
          <AnotherCard number={688} />
        </div>
      );
    }
    
    // Render the application to the DOM
    ReactDOM.render(<App />, document.getElementById("root"));
    <script src="https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js"></script>
    
    <div id="root"></div>

    Example with API

    // Import the React and ReactDOM modules
    const { useState, useEffect } = React;
    
    // The component receives the passed values as object (props)
    function Card(props) {
      const digits = `${props.number}`.split('');
     
      return (
        <div style={{ display: "flex" }}>
          {digits.map((val) => (
            <div
              style={{
                fontSize: 42,
                marginRight: 10,
                background: "#8D0000",
                color: "white",
                width: 40,
                height: 55,
                fontWeight: "bold",
                textAlign: "center"
              }}
            >
              {val}
            </div>
          ))}
        </div>
      );
    }
    
    // Instead of declaring the object (props), you can directly declare the parameters within { and }
    // That's called "Destructuring assignment"
    function AnotherCard({ number }) {
      const digits = `${number}`.split('');
     
      return (
        <div style={{ display: "flex" }}>
          {digits.map((val) => (
            <div
              style={{
                fontSize: 42,
                marginRight: 10,
                background: "#8D0000",
                color: "white",
                width: 40,
                height: 55,
                fontWeight: "bold",
                textAlign: "center"
              }}
            >
              {val}
            </div>
          ))}
        </div>
      );
    }
    
    // App component
    function App() {
      // Declare visitor with default object
      const [visitor, setVisitor] = useState({
        count: 0,
        click: 0
      });
    
      // Request data of visitor
      useEffect(() => {
        fetch('https://count.cab/hit/ghG6Oirn0b')
          .then(response => response.json())
          .then(v =>  setVisitor(v));
      }, []);
      
      // Will see that the code runs first, and the fetch will update the visitor value asynchronously
      console.log(visitor)
    
      return (
        <div style={{ display: "grid", gap: "10px" }}>
          Example #1 (Card component with props object)
          <Card number={visitor.count} />
          
          Example #2 (AnotherCard component with destructuring assignment)
          <AnotherCard number={visitor.count} />
        </div>
      );
    }
    
    // Render the application to the DOM
    ReactDOM.render(<App />, document.getElementById("root"));
    <script src="https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js"></script>
    
    <div id="root"></div>

    Example with API & extra zero digits

    // Import the React and ReactDOM modules
    const { useState, useEffect } = React;
    
    // How many digits in total do we want to display
    const DIGIT_COUNT = 5
    
    // The component receives the passed values as object (props)
    function Card(props) {
      let digits = `${props.number}`.split('');
      // Determine the number of digits
      const numDigits = digits.length;
      // If the number has less than DIGIT_COUNT digits, add leading zeros
      if (numDigits < DIGIT_COUNT) {
        digits = Array(DIGIT_COUNT - numDigits).fill(0).concat(digits);
      }
    
      return (
        <div style={{ display: "flex" }}>
          {digits.map((val, index) => (
            <div
              key={index}
              style={{
                fontSize: 42,
                marginRight: 10,
                background: "#8D0000",
                color: "white",
                width: 40,
                height: 55,
                fontWeight: "bold",
                textAlign: "center"
              }}
            >
              {val}
            </div>
          ))}
        </div>
      );
    }
    
    // Instead of declaring the object (props), you can directly declare the parameters within { and }
    // That's called "Destructuring assignment"
    function AnotherCard({ number }) {
      let digits = `${number}`.split('');
      // Determine the number of digits
      const numDigits = digits.length;
      // If the number has less than DIGIT_COUNT digits, add leading zeros
      if (numDigits < DIGIT_COUNT) {
        digits = Array(DIGIT_COUNT - numDigits).fill(0).concat(digits);
      }
    
      return (
        <div style={{ display: "flex" }}>
          {digits.map((val, index) => (
            <div
              key={index}
              style={{
                fontSize: 42,
                marginRight: 10,
                background: "#8D0000",
                color: "white",
                width: 40,
                height: 55,
                fontWeight: "bold",
                textAlign: "center"
              }}
            >
              {val}
            </div>
          ))}
        </div>
      );
    }
    
    // App component
    function App() {
      // Declare visitor with default object
      const [visitor, setVisitor] = useState({
        count: 0,
        click: 0
      });
    
      // Request data of visitor
      useEffect(() => {
        fetch('https://count.cab/hit/ghG6Oirn0b')
          .then(response => response.json())
          .then(v =>  setVisitor(v));
      }, []);
    
      return (
        <div style={{ display: "grid", gap: "10px" }}>
          Example #1 (Card component with props object)
          <Card number={visitor.count} />
          
          Example #2 (AnotherCard component with destructuring assignment)
          <AnotherCard number={visitor.count} />
        </div>
      );
    }
    
    // Render the application to the DOM
    ReactDOM.render(<App />, document.getElementById("root"));
    <script src="https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js"></script>
    
    <div id="root"></div>