skip to Main Content

I have a react application used to take attendance. The attendance records the time of signin.
The problem I am facing with the app is that the time doesn’t get updated with real time. After the first render of the app, the time remains constant. (The time gets updated when the app gets reloaded though)
The code I am supplying is just a sample of the whole problem, but it expresses the problem fully.

App.js

import React from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Signin from './pages/Signin';

export const date = new Date();
export const options = { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: true };
const currentTime = new Intl.DateTimeFormat('en-US', options).format(date);
export const currTime = currentTime.slice(0, 8);

export default function App() {
  return (
    <div className='App'>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Signin />} />
        </Routes>
      </BrowserRouter>
    </div>
  );
}

Signin.js

import React from 'react';
import { currTime } from '../App';

function Signin() {
    React.useEffect(() => {
        const interval = setInterval(() => {
            console.log(currTime);
        }, 1000);
        return () => {
            clearInterval(interval);
        }
    }, []);
    return (<>Sign In</>);
}
export default Signin;

The same value is logged each time the interval runs
For example, if I ran this at 05:38:25, I will keep getting 05:38:25 even by another time like 05:48:25.
How do I fix this, such that I will get 05:48:25 by 05:48:25 even if the app was rendered by 05:38:25

3

Answers


  1. import React, { useState, useEffect } from ‘react’;

    function Signin() {
    const [currentTime, setCurrentTime] = useState(new Date());

    useEffect(() => {
        const interval = setInterval(() => {
            setCurrentTime(new Date());
        }, 1000);
    
        return () => clearInterval(interval);
    }, []);
    
    return (
        <>
            <div>Current Time: {currentTime.toLocaleTimeString()}</div>
            <div>Sign In</div>
        </>
    );
    

    }

    export default Signin;

    Login or Signup to reply.
  2. The issue you’re facing is related to the fact that the currTime value is computed only once during the initial rendering of the App component and doesn’t get updated afterward. To achieve real-time updates, you need to use the useState hook to manage the current time in the Signin component and update it at regular intervals.

    import React, { useState, useEffect } from 'react';
    import { BrowserRouter, Route, Routes } from 'react-router-dom';
    export default function App() {
      return (
        <div className='App'>
          <BrowserRouter>
            <Routes>
              <Route path="/" element={<Signin />} />
            </Routes>
          </BrowserRouter>
        </div>
      );
    }
    function Signin() {
      const [currentTime, setCurrentTime] = useState(getCurrentTime());
      useEffect(() => {
        const interval = setInterval(() => {
          setCurrentTime(getCurrentTime());
        }, 1000);
        return () => {
          clearInterval(interval);
        };
      }, []);
      function getCurrentTime() {
        const date = new Date();
        const options = { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: true };
        return new Intl.DateTimeFormat('en-US', options).format(date).slice(0, 8);
      }
      return (
        <>
          <div>Current Time: {currentTime}</div>
          <div>Sign In</div>
        </>
      );
    }
    
    Login or Signup to reply.
    1. Create a function using your conversion requirements. This can be exported for use in both React and anything else that requires it.
    2. Create a custom hook that you can import into the components that need it – this uses an interval to store the current formatted time. This way you’re extracting the logic for the time into one place.
    3. Import the custom hook into the components that need to use it.
    const { useState, useEffect } = React;
    
    // Your date -> time conversion function which you can also
    // export to where it's needed (no React required)
    function formatToTime(date) {
      const options = { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: true };
      return new Intl.DateTimeFormat('en-US', options).format(date);
    }
    
    // A custom hook that updates its state to the formatted time
    // It would import the function specified above
    function useCurrentTime() {
    
      const [currentTime, setCurrentTime] = useState(formatToTime(new Date()));
      
      useEffect(() => {
        const interval = setInterval(() => {
          setCurrentTime(formatToTime(new Date()));
        }, 1000);
        return () => clearInterval(interval);
      }, []); 
      
      return currentTime;
      
    }
    
    // And you can use the custom hook in any component you want
    // Here I'm including it in the main component...
    function Example() {
    
      const currentTime = useCurrentTime();
      
      return (
        <div>
          <p>Current time is: {currentTime}</p>
          <AnotherComponent />
        </div>
      );
    
    }
    
    // ...and also a separate component
    function AnotherComponent() {
    
      const currentTime = useCurrentTime();
    
      return (
        <p className="red">Current time is: {currentTime}</p>
      );
     
    }
    
    const node = document.getElementById('root');
    const root = ReactDOM.createRoot(node);
    root.render(<Example />);
    .red { color: red; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
    <div id="root"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search