diff --git a/README.md b/README.md
index e5fc0e848..c2eec0bcb 100644
--- a/README.md
+++ b/README.md
@@ -88,6 +88,7 @@ import ReactDOM from 'react-dom';
* [Carousel](#carousel)
* [Collapse](#collapse)
+* [CountDown](#countdown)
* [FileDrop](#filedrop)
* [Mailto](#mailto)
* [StarRating](#starrating)
@@ -798,6 +799,98 @@ ReactDOM.render(
[⬆ Back to top](#table-of-contents)
+### CountDown
+
+Renders a countdown timer that prints a message when it reaches zero.
+
+Use object destructuring to set defaults for the `hours`, `minutes` and `seconds` props.
+Use the `React.useState()` hook to create the `time`, `paused` and `over` state variables and set their values to the values of the passed props, `false` and `false` respectively.
+Create a method `tick`, that updates the value of `time` based on the current value (i.e. decreasing the time by one second).
+If `paused` or `over` is `true`, `tick` will return immediately.
+Create a method `reset`, that resets all state variables to their initial states.
+Use the the `React.useEffect()` hook to call the `tick` method every second via the use of `setInterval()` and use `clearInterval()` to cleanup when the component is unmounted.
+Use a `
` to wrap a `
` element with the textual representation of the components `time` state variable, as well as two `` elements that will pause/unpause and restart the timer respectively.
+If `over` is `true`, the timer will display a message instead of the value of `time`.
+
+```jsx
+function CountDown({ hours = 0, minutes = 0, seconds = 0 }) {
+ const [paused, setPaused] = React.useState(false);
+ const [over, setOver] = React.useState(false);
+ const [time, setTime] = React.useState({
+ hours: parseInt(hours),
+ minutes: parseInt(minutes),
+ seconds: parseInt(seconds)
+ });
+
+ const tick = () => {
+ if (paused || over) return;
+ if (time.hours == 0 && time.minutes == 0 && time.seconds == 0)
+ setOver(true);
+ else if (time.minutes == 0 && time.seconds == 0)
+ setTime({
+ hours: time.hours - 1,
+ minutes: 59,
+ seconds: 59
+ });
+ else if (time.seconds == 0)
+ setTime({
+ hours: time.hours,
+ minutes: time.minutes - 1,
+ seconds: 59
+ });
+ else
+ setTime({
+ hours: time.hours,
+ minutes: time.minutes,
+ seconds: time.seconds - 1
+ });
+ };
+
+ const reset = () => {
+ setTime({
+ hours: parseInt(hours),
+ minutes: parseInt(minutes),
+ seconds: parseInt(seconds)
+ });
+ setPaused(false);
+ setOver(false);
+ };
+
+ React.useEffect(() => {
+ let timerID = setInterval(() => tick(), 1000);
+ return () => clearInterval(timerID);
+ });
+
+ return (
+
+
{`${time.hours
+ .toString()
+ .padStart(2, "0")}:${time.minutes
+ .toString()
+ .padStart(2, "0")}:${time.seconds.toString().padStart(2, "0")}`}
+
{over ? "Time's up!" : ""}
+
setPaused(!paused)}>
+ {paused ? "Resume" : "Pause"}
+
+
reset()}>Restart
+
+ );
+}
+```
+
+
+Examples
+
+```jsx
+ReactDOM.render(
+ ,
+ document.getElementById('root')
+);
+```
+
+
+ [⬆ Back to top](#table-of-contents)
+
### FileDrop
Renders a file drag and drop component for a single file.
diff --git a/data/snippet_data.json b/data/snippet_data.json
index 1c63758ab..740446b61 100644
--- a/data/snippet_data.json
+++ b/data/snippet_data.json
@@ -48,6 +48,21 @@
],
"notes": []
},
+ {
+ "name": "CountDown.md",
+ "title": "CountDown",
+ "text": "Renders a countdown timer that prints a message when it reaches zero.\n\nUse object destructuring to set defaults for the `hours`, `minutes` and `seconds` props.\nUse the `React.useState()` hook to create the `time`, `paused` and `over` state variables and set their values to the values of the passed props, `false` and `false` respectively.\nCreate a method `tick`, that updates the value of `time` based on the current value (i.e. decreasing the time by one second).\nIf `paused` or `over` is `true`, `tick` will return immediately.\nCreate a method `reset`, that resets all state variables to their initial states.\nUse the the `React.useEffect()` hook to call the `tick` method every second via the use of `setInterval()` and use `clearInterval()` to cleanup when the component is unmounted.\nUse a `` to wrap a `
` element with the textual representation of the components `time` state variable, as well as two `` elements that will pause/unpause and restart the timer respectively.\nIf `over` is `true`, the timer will display a message instead of the value of `time`.\n\n",
+ "codeBlocks": [
+ "```jsx\nfunction CountDown({ hours = 0, minutes = 0, seconds = 0 }) {\n const [paused, setPaused] = React.useState(false);\n const [over, setOver] = React.useState(false);\n const [time, setTime] = React.useState({\n hours: parseInt(hours),\n minutes: parseInt(minutes),\n seconds: parseInt(seconds)\n });\n\n const tick = () => {\n if (paused || over) return;\n if (time.hours == 0 && time.minutes == 0 && time.seconds == 0)\n setOver(true);\n else if (time.minutes == 0 && time.seconds == 0)\n setTime({\n hours: time.hours - 1,\n minutes: 59,\n seconds: 59\n });\n else if (time.seconds == 0)\n setTime({\n hours: time.hours,\n minutes: time.minutes - 1,\n seconds: 59\n });\n else\n setTime({\n hours: time.hours,\n minutes: time.minutes,\n seconds: time.seconds - 1\n });\n };\n\n const reset = () => {\n setTime({\n hours: parseInt(hours),\n minutes: parseInt(minutes),\n seconds: parseInt(seconds)\n });\n setPaused(false);\n setOver(false);\n };\n\n React.useEffect(() => {\n let timerID = setInterval(() => tick(), 1000);\n return () => clearInterval(timerID);\n });\n\n return (\n \n
{`${time.hours\n .toString()\n .padStart(2, \"0\")}:${time.minutes\n .toString()\n .padStart(2, \"0\")}:${time.seconds.toString().padStart(2, \"0\")}`}
\n
{over ? \"Time's up!\" : \"\"}
\n
setPaused(!paused)}>\n {paused ? \"Resume\" : \"Pause\"}\n \n
reset()}>Restart \n
\n );\n}\n```",
+ "```jsx\nReactDOM.render(\n ,\n document.getElementById('root')\n);\n```"
+ ],
+ "expertise": 2,
+ "tags": [
+ "visual",
+ "state"
+ ],
+ "notes": []
+ },
{
"name": "DataList.md",
"title": "DataList",