Daniyal Maniar
Daniyal Maniar

Reputation: 95

How to reset the timer component upon completion

I am trying to build a timer component using the react-countdown-now package: https://www.npmjs.com/package/react-countdown-now#key.

I was having trouble to reset the timer so that it moves on to the next time on the schedule.

I have been trying to use key property in props it pass it in an array of times to wait till (it was in the documentation). In reality I would get these values of a schedule from a server side method.

Currently I have

Component:

<Countdown
     date={Date.now() + 5000}
     key = {timeDelays}
     intervalDelay={0}
     precision={3}
     renderer={timerRenderer}
/>

Supporting functions and Values:

//These time values are most probably going to be in JSON format, 
//and probably will contain EPOCH times for scheduled events

const timeDelays = [2000,4000,3000,15789,2345794];

// Random component
const Completionist = () => <span>You are good to go!</span>;

// Renderer callback with condition
const timerRenderer = ({ hours, minutes, seconds, completed }) => {
     // if (completed) {
        //     Render a completed state
        //     return <Completionist />;
     // } else {
     //     // Render a countdown
            return <span>{hours}:{minutes}:{seconds}</span>;
     //}
};

I want it to start with a countdown from the list and then when completed move onto the next schedule value from the list.

Upvotes: 2

Views: 5561

Answers (3)

Daniel Barde
Daniel Barde

Reputation: 2703

This is a total change from the former answer, which used a class-based component.

First, we'll need to import React and React hooks to our component file.

import React, { useState } from 'react';

Next, we'll declare a React function component and use React hooks to maintain state.

function MyCountdownTimer({ times }) {
    // a hook for the current time index
    const [currentTimeIndex, setCurrentTimeIndex] = useState(0);
    // a hook for the current time
    const [currentTime, setCurrentTime] = useState(null);
    // return a render
    return (
        <Countdown
            date={currentTime}
            key={currentTimeIndex}
            onComplete={() => {
                // dont's move to next time if just done with last time
                if(times.length - 1 <= times.indexOf(currentTime)) return;
                // move to next time index
                setCurrentTimeIndex(currentTimeIndex + 1);
                // reset current time
                setCurrentTime(new Date(times[currentTimeIndex + 1]));
            }}
            renderer={({ hours, minutes, seconds, completed }) => {
                // render completed
                if (completed) return <span>You are good to go!</span>;
                // render current countdown time
                return <span>{hours}:{minutes}:{seconds}</span>;

            }}
        />
    );
}

An implementation of this would look something like so.

let times = [...] // an array of times

<MyCountdownTimer times={times} />

React hooks are still a bit new so for a better understanding on React Hooks you can follow this link https://reactjs.org/docs/hooks-intro.html.

NOTE

  1. You need a way to tell what time you're currently on so within your component you'll have two things. The list of times(times) as an array this should be passed as a prop as suggested in the code above, the index of the current time(currentTimeIndex) as an integer and the current time(currentTime) as a Date object.

  2. You'll need to listen for when the timer hits zero using the onComplete property to define a callback method, we do not update the component's state when the Countdown timer has been completed.

  3. A key property on the Countdown component, this is meant to change for each time you want to reset the countdown timer and since we're incrementing the index to go to the next time we'll simply use the index of the current time.

  4. I reduced the code of your renderer so you can render what you need to within the same function, except if you will be adding a lot more code in there than that.

  5. This is using a function component with hooks to maintain state.

  6. The date according to the documentation can be a date object.

Upvotes: 4

Arshad
Arshad

Reputation: 343

Just you need to change the value of key attribute key={new values or updated value} so automatically re set the timer.

key This is one of React's internal component props and is used to identify the component. However, we can leverage this behaviour and use it to, for example, restart the countdown by passing in a new string or number.https://www.npmjs.com/package/react-countdown

Upvotes: 2

Daniyal Maniar
Daniyal Maniar

Reputation: 95

I guess my translated component would look like this

const WebPage = (props) => {
        const timerState = {
                times:[Date.now()+5000,Date.now()+12000,Date.now()+17000,Date.now()+22000],
                currentTimeIndex: 0,
                currentTime: Date.now(),
        } ;
        const timerRenderer = ({ hours, minutes, seconds, completed }) => {
                if (completed) return <span> No more Scheduled time</span>;
                return <span>{hours}:{minutes}:{seconds}</span>;
        };
        const completeTime = () => {
                if (timerState.times.length - 1 <= times.indexOf(timerState.currentTime)) return;
                // move to next time
                timerState.currentTimeIndex++;
                timerState.currentTime = new Date(timerState.times[timerState.currentTimeIndex+1])
        };
        return (
                <Countdown
                     date={timerState.currentTime}
                     key = {timerState.currentTimeIndex}
                     onComplete={completeTime}
                     intervalDelay={0}
                     precision={3}
                     renderer={timerRenderer}
                />
        ) 
}

It's not exactly working as it by default goes to "No more Scheduled time", and if I get rid of the if(completed) it just stays at 0:0:0.

Upvotes: 1

Related Questions