I am using https://github.com/pqina/flip & want to implement Tick.count.down()
method using React. There's no React specific code that is given in the example & also the author is swamped so thought I'd ask here for some React experts.
I've cloned the above repo & replaced https://github.com/pqina/flip/tree/master/example/index.html contents with the following code.
I have the following HTML working perfectly:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>Count Down</title>
<link rel="stylesheet" href="../dist/core/tick.core.min.css" />
</head>
<body>
<style>
.tick {
font-size: 2rem;
}
</style>
<p>Countdown from 10</p>
<div class="tick" data-did-init="startNumericCountdown">
<span data-view="text"></span>
</div>
<script>
function startNumericCountdown(tick) {
console.log(`start numeric countdown...`)
var counter = Tick.count.down(10, 'seconds')
counter.onupdate = function (value) {
tick.value = value
}
counter.onended = function () {
console.log(`countdown over 😟`)
}
}
</script>
<script src="../dist/core/tick.core.kickstart.min.js"></script>
</body>
</html>
The problem comes when I try to convert it into React. Currently, I have the following code:
import React, { useRef, useEffect } from "react";
import Tick from "@pqina/flip";
import "@pqina/flip/dist/flip.min.css";
export const FlipDate = ({ value }) => {
const divRef = useRef();
const tickRef = useRef();
useEffect(() => {
const didInit = tick => {
console.log("didInit");
console.log({ tick });
tickRef.current = tick;
};
const currDiv = divRef.current;
const tickValue = tickRef.current;
Tick.DOM.create(currDiv, {
value: Tick.count.down(10, 'seconds'),
didInit
});
// divRef.current = Tick.count.down(10, 'seconds');
return () => Tick.DOM.destroy(tickValue);
});
useEffect(() => {
console.log({ tickRef });
if (tickRef.current) {
console.log({ divRef });
tickRef.current.value = value;
}
}, [value]);
return (
<div ref={divRef} className="tick">
<div data-repeat="true">
<span data-view="flip">Tick</span>
</div>
</div>
);
};
This does not work as expected. I've got the basic flip
library working as you can see in my demo here: https://codesandbox.io/s/react-flip-countdown-timer-8tin3?file=/src/App.js
3 of the files are the same code: 1 being using class component Flip.js
, 2 using Hooks Flipr.js
& Flippen.js
.
I want to make FlipDate.js
working. It should count down from 10 seconds to 0 seconds. Been trying this for the last week but couldn't wrap my head around this. Any help is appreciated 🙏
Sidenote: https://github.com/pqina/flip uses https://github.com/pqina/tick underhood.
I posted the same question on Reddit at /r/reactjs as well & found the answer there. Here's a working solution:
import React, { useRef, useEffect, useState } from "react";
import Tick from "@pqina/flip";
import "@pqina/flip/dist/flip.min.css";
export const WorkingFlipDate = ({ value }) => {
const divRef = useRef();
const tickRef = useRef();
const [tickValue, setTickValue] = useState(value);
// Make the Tick instance and store it in the refs
useEffect(() => {
const didInit = tick => {
tickRef.current = tick;
};
const currDiv = divRef.current;
const tickValue = tickRef.current;
Tick.DOM.create(currDiv, {
value,
didInit
});
return () => Tick.DOM.destroy(tickValue);
}, [value]);
// Start the Tick.down process
useEffect(() => {
const counter = Tick.count.down(value, {
format: ["d", "h", "m", "s"]
});
// When the counter updates, update React's state value
counter.onupdate = function(value) {
setTickValue(value);
};
// TODO: I don't know how to destroy this
return () => {
counter.onupdate = () => {};
};
}, [value]);
// When the tickValue is updated, update the Tick.DOM element
useEffect(() => {
if (tickRef.current) {
tickRef.current.value = tickValue;
}
}, [tickValue]);
return (
<div ref={divRef} className="tick">
<div data-repeat="true">
<span data-view="flip">Tick</span>
</div>
</div>
);
};