vydimitrov / react-countdown-circle-timer

Lightweight React/React Native countdown timer component with color and progress animation based on SVG
MIT License
692 stars 87 forks source link

Timer text and flip counter does not work in Class-based React Component #10

Closed HolimaX closed 4 years ago

HolimaX commented 4 years ago

I am trying to use your react module. I m now testing it locally in in online sandbox, but w/o success. See following URL for online sandbox: https://codesandbox.io/embed/divine-dawn-qpnci?fontsize=14&hidenavigation=1&theme=dark

The code from sandbox above produces error:

image

When I try to run it in my environment with this code:

import React from "react";
import { CountdownCircleTimer } from "react-countdown-circle-timer";

import "./styles.css";

class Countdown extends React.Component {
  renderTime = value => {
    if (value === 0) {
      return <div className="timer">Too lale...</div>;
    }

    return (
      <div className="timer">
        <div className="text">Remaining</div>
        <div className="value">{value}</div>
        <div className="text">seconds</div>
      </div>
    );
  };

  renderTime = time => {
    const currentTime = React.useRef(time);
    const prevTime = React.useRef(null);
    const isNewTimeFirstTick = React.useRef(false);
    const [_, setOneLastRerender] = React.useState(0);

    if (currentTime.current !== time) {
      isNewTimeFirstTick.current = true;
      prevTime.current = currentTime.current;
      currentTime.current = time;
    } else {
      isNewTimeFirstTick.current = false;
    }

    // force one last re-render when the time is over to tirgger the last animation
    if (time === 0) {
      setTimeout(() => {
        setOneLastRerender(val => val + 1);
      }, 20);
    }

    const isTimeUp = isNewTimeFirstTick.current;

    return (
      <div className="time-wrapper">
        <div key={time} className={`time ${isTimeUp ? "up" : ""}`}>
          {time}
        </div>
        {prevTime.current !== null && (
          <div
            key={prevTime.current}
            className={`time ${!isTimeUp ? "down" : ""}`}
          >
            {prevTime.current}
          </div>
        )}
      </div>
    );
  };

  render() {
    return (
      <div className="countdown-wrapper">
        <div className="countdown-item">
          <CountdownCircleTimer
            isPlaying
            renderTime={() => {
              this.renderTime();
            }}
            onComplete={() => {
              // do your stuff here
              return [true, 1500]; // repeat animation in 1.5 seconds
            }}
            durationSeconds={60}
            initialRemainingTime={15}
            colors={[["#A30000"]]}
          />
        </div>
      </div>
    );
  }
}

export default Countdown;

Once I remove the offending lines, I see white page when using test sandbox below or no text, if running locally in actual website.

You can test it here: https://codesandbox.io/embed/divine-dawn-qpnci?fontsize=14&hidenavigation=1&theme=dark

Could you please provide fix or show example how to use your module in Class-based React JS project?

vydimitrov commented 4 years ago

There are several problems with your code:

const rootElement = document.getElementById("root"); ReactDOM.render(

, rootElement ); ``` - In your Class component you have `renderTime` method defined twice - You can not use hooks in Class components - please read the docs - https://reactjs.org/docs/hooks-faq.html#should-i-use-hooks-classes-or-a-mix-of-both My recommendation: - Use my basic codesandbox to play with the timer - https://codesandbox.io/s/stoic-cache-e7cie?fontsize=14&hidenavigation=1&theme=dark - Do not use Class components unless there is no other way .... If you have really good reason for using Class component then you will need to rewrite the code above so it uses `state` instead of hooks - Read a bit more about React :)
HolimaX commented 4 years ago

There are several problems with your code:

  • You are missing the part where you initialize React, something like below:
import React from "react";
import ReactDOM from "react-dom";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);

My recommendation:

Hmm.

Can you please give code example in Class-based component? I am new to react and some example would not hurt.

Thanks :)

vydimitrov commented 4 years ago

If you are new to React I'd recommend starting with functional components. If I find some time, I will prep Class-based demo.

HolimaX commented 4 years ago

If you are new to React I'd recommend starting with functional components. If I find some time, I will prep Class-based demo.

Thanks, sounds great. Looking forward for an example.

HolimaX commented 4 years ago

Any chance to update README.md with example for Class-based component? I really would love to get the numbers visible in the center of the circle.. :)

Also, the sentence "Feed the renderTime function above to the CountdownCircleTimer renderTime prop and add the styles above to your stylesheet." is very confusing to newcomers to React stuff. Can you add more details or just add example how it all looks together? Please?

vydimitrov commented 4 years ago

Hey there, here you go - your demo with Class component - https://codesandbox.io/s/friendly-noether-w2mkz

You can find all styles in styles.css, the Class component is in App.jsx. Hope this will help you to start with it. Also please consider using functional components as the rest of the React developers :)