diff --git a/snippets/CountDown.md b/snippets/CountDown.md
index f7fce6729..96c4c2772 100644
--- a/snippets/CountDown.md
+++ b/snippets/CountDown.md
@@ -5,71 +5,51 @@ tags: components,state,advanced
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.
+- Use the `useState()` hook to create a state variable to hold the time value, initialize it from the props and destructure it into its components.
+- Use the `useState()` hook to create the `paused` and `over` state variables, used to prevent the timer from ticking if it's paused or the time has run out.
+- Create a method `tick`, that updates the time values based on the current value (i.e. decreasing the time by one second).
- 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`.
+- Use the the `useEffect()` hook to call the `tick` method every second via the use of `setInterval()` and use `clearInterval()` to clean up when the component is unmounted.
+- Use `String.prototype.padStart()` to pad each part of the time array to two characters to create the visual representation of the timer.
```jsx
const 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 [[h, m, s], setTime] = React.useState([hours, minutes, 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
- });
+ if (h === 0 && m === 0 && s === 0) setOver(true);
+ else if (m === 0 && s === 0) {
+ setTime([h - 1, 59, 59]);
+ } else if (s == 0) {
+ setTime([h, m - 1, 59]);
} else {
- setTime({
- hours: time.hours,
- minutes: time.minutes,
- seconds: time.seconds - 1
- });
+ setTime([h, m, s - 1]);
}
};
const reset = () => {
- setTime({
- hours: parseInt(hours),
- minutes: parseInt(minutes),
- seconds: parseInt(seconds)
- });
+ setTime([parseInt(hours), parseInt(minutes), parseInt(seconds)]);
setPaused(false);
setOver(false);
};
React.useEffect(() => {
- let timerID = setInterval(() => tick(), 1000);
+ const timerID = setInterval(() => tick(), 1000);
return () => clearInterval(timerID);
});
return (
-
{`${time.hours.toString().padStart(2, '0')}:${time.minutes
+
{`${h.toString().padStart(2, '0')}:${m
.toString()
- .padStart(2, '0')}:${time.seconds.toString().padStart(2, '0')}`}
+ .padStart(2, '0')}:${s.toString().padStart(2, '0')}`}
{over ? "Time's up!" : ''}
-
setPaused(!paused)}>{paused ? 'Resume' : 'Pause'}
+
setPaused(!paused)}>
+ {paused ? 'Resume' : 'Pause'}
+
reset()}>Restart
);
@@ -77,5 +57,8 @@ const CountDown = ({ hours = 0, minutes = 0, seconds = 0 }) => {
```
```jsx
-ReactDOM.render( , document.getElementById('root'));
+ReactDOM.render(
+ ,
+ document.getElementById('root')
+);
```
diff --git a/snippets/MultiselectCheckbox.md b/snippets/MultiselectCheckbox.md
index 28419db29..7aa325ab7 100644
--- a/snippets/MultiselectCheckbox.md
+++ b/snippets/MultiselectCheckbox.md
@@ -5,45 +5,38 @@ tags: components,input,state,array,intermediate
Renders a checkbox list that uses a callback function to pass its selected value/values to the parent component.
-- Use `React.useState()` to create a `data` state variable and set its initial value equal to the `options` prop.
-- Create a function `toggle` that is used to toggle the `checked` to update the `data` state variable and call the `onChange` callback passed via the component's props.
-- Render a `` element and use `Array.prototype.map()` to map the `data` state variable to individual `` elements with ` ` elements as their children.
-- Each ` ` element has the `type='checkbox'` attribute and is marked as `readOnly`, as its click events are handled by the parent ` ` element's `onClick` handler.
+- Use the `useState()` hook to create the `data` state variable and use the `options` prop to initialize its value.
+- Create a `toggle` function that uses the spread operator (`...`) and `Array.prototype.splice()` to update the `data` state variable and call the `onChange` callback with any `checked` options.
+- Use `Array.prototype.map()` to map the `data` state variable to individual ` ` elements, each one wrapped in a ``, binding the `onClick` handler to the `toggle` function.
```jsx
-const style = {
- listContainer: {
- listStyle: 'none',
- paddingLeft: 0
- },
- itemStyle: {
- cursor: 'pointer',
- padding: 5
- }
-};
-
const MultiselectCheckbox = ({ options, onChange }) => {
const [data, setData] = React.useState(options);
- const toggle = item => {
- data.forEach((_, key) => {
- if (data[key].label === item.label) data[key].checked = !item.checked;
+ const toggle = index => {
+ const newData = [...data];
+ newData.splice(index, 1, {
+ label: data[index].label,
+ checked: !data[index].checked
});
- setData([...data]);
- onChange(data);
+ setData(newData);
+ onChange(newData.filter(x => x.checked));
};
return (
-
+ <>
+ {data.map((item, index) => (
+
+ toggle(index)}
+ />
+ {item.label}
+
+ ))}
+ >
);
};
```
diff --git a/snippets/StarRating.md b/snippets/StarRating.md
index a414d670d..000865fea 100644
--- a/snippets/StarRating.md
+++ b/snippets/StarRating.md
@@ -6,39 +6,47 @@ tags: components,children,input,state,intermediate
Renders a star rating component.
- Define a component, called `Star` that will render each individual star with the appropriate appearance, based on the parent component's state.
-- In the `StarRating` component, use the `React.useState()` hook to define the `rating` and `selection` state variables with the initial values of `value` (or `0` if invalid or not supplied) and `0`.
-- Create a method, `hoverOver`, that updates `selected` and `rating` according to the provided `event`.
-- Create a `` to wrap the `
` components, which are created using `Array.prototype.map()` on an array of 5 elements, created using `Array.from()`, and handle the `onMouseLeave` event to set `selection` to `0`, the `onClick` event to set the `rating` and the `onMouseOver` event to set `selection` to the `star-id` attribute of the `event.target` respectively.
-- Finally, pass the appropriate values to each `` component (`starId` and `marked`).
+- In the `StarRating` component, use the `useState()` hook to define the `rating` and `selection` state variables with the appropriate initial values.
+- Create a method, `hoverOver`, that updates `selected` according to the provided `event`, using the .`data-star-id` attribute of the event's target or resets it to `0` if called with a `null` argument.
+- Use `Array.from()` to create an array of `5` elements and `Array.prototype.map()` to create individual `` components.
+- Handle the `onMouseOver` and `onMouseLeave` events of the wrapping element using `hoverOver` and the `onClick` event using `setRating`.
+
+```css
+.star {
+ color: #ff9933;
+ cursor: pointer;
+}
+```
```jsx
const Star = ({ marked, starId }) => {
return (
-
+
{marked ? '\u2605' : '\u2606'}
);
};
const StarRating = ({ value }) => {
- const [rating, setRating] = React.useState(typeof value == 'number' ? value : 0);
+ const [rating, setRating] = React.useState(parseInt(value) || 0);
const [selection, setSelection] = React.useState(0);
+
const hoverOver = event => {
let val = 0;
- if (event && event.target && event.target.getAttribute('star-id'))
- val = event.target.getAttribute('star-id');
+ if (event && event.target && event.target.getAttribute('data-star-id'))
+ val = event.target.getAttribute('data-star-id');
setSelection(val);
};
return (
hoverOver(null)}
- onClick={event => setRating(event.target.getAttribute('star-id') || rating)}
+ onClick={e => setRating(e.target.getAttribute('data-star-id') || rating)}
onMouseOver={hoverOver}
>
{Array.from({ length: 5 }, (v, i) => (
= i + 1 : rating >= i + 1}
/>
))}
@@ -48,6 +56,5 @@ const StarRating = ({ value }) => {
```
```jsx
-ReactDOM.render( , document.getElementById('root'));
ReactDOM.render( , document.getElementById('root'));
```