# Intro To React

## Introduction to React for Complete Beginners

All of the code examples below will be included a second time at the bottom of this article as an embedded gist.

***

#### Introduction to React for Complete Beginners

All of the code examples below will be included a second time at the bottom of this article as an embedded gist, so that it is properly syntax highlighted.

React uses a syntax extension of JavaScript called JSX that allows you to write HTML directly within JavaScript.

![](https://cdn-images-1.medium.com/max/1200/0*Olfj44MF6WSzvlSM.png)

#### React

> *React uses a syntax extension of JavaScript called JSX that allows you to write HTML directly within JavaScript*

> *because JSX is a syntactic extension of JavaScript, you can actually write JavaScript directly within JSX*

> *include the code you want to be treated as JavaScript within curly braces: { 'this is treated as JavaScript code' }*

> *JSX code must be compiled into JavaScript*

> *under the hood the challenges are calling ReactDOM.render (JSX, document.getElementById('root'))*

> *One important thing to know about nested JSX is that it must return a single element.*

> *For instance, several JSX elements written as siblings with no parent wrapper element will not transpile.*

***

#### From the React Docs:

#### What is React?

React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called “components”.

React has a few different kinds of components, but we'll start with `React.Component` subclasses:

```
class ShoppingList extends React.Component {
  render() {
    return (
      <div className="shopping-list">
        <h1>Shopping List for {this.props.name}</h1>
        <ul>
          <li>Instagram</li>
          <li>WhatsApp</li>
          <li>Oculus</li>
        </ul>
      </div>
    );
  }
}

// Example usage: <ShoppingList name="Mark" />
```

We'll get to the funny XML-like tags soon. We use components to tell React what we want to see on the screen. When our data changes, React will efficiently update and re-render our components.

Here, ShoppingList is a **React component class**, or **React component type**. A component takes in parameters, called `props` (short for “properties”), and returns a hierarchy of views to display via the `render` method.

The `render` method returns a *description* of what you want to see on the screen. React takes the description and displays the result. In particular, `render` returns a **React element**, which is a lightweight description of what to render. Most React developers use a special syntax called “JSX” which makes these structures easier to write. The `<div />` syntax is transformed at build time to `React.createElement('div')`. The example above is equivalent to:

```
return React.createElement('div', {className: 'shopping-list'},
  React.createElement('h1', /* ... h1 children ... */),
  React.createElement('ul', /* ... ul children ... */)
);
```

***

#### Valid JSX:

```
<div>
  <p>Paragraph One</p>
  <p>Paragraph Two</p>
  <p>Paragraph Three</p>
</div>
```

***

#### Invalid JSX:

```
<p>Paragraph One</p>
<p>Paragraph Two</p>
<p>Paragraph Three</p>
```

**To put comments inside JSX, you use the syntax {/\* \*/} to wrap around the comment text.**

To put comments inside JSX, you use the syntax {/\* \*/} to wrap around the comment text.

The code editor has a JSX element similar to what you created in the last challenge. Add a comment somewhere within the provided div element, without modifying the existing h1 or p elements.

```
const JSX = (
  <div>
  {/* This is a comment */}
    <h1>This is a block of JSX</h1>
    <p>Here's a subtitle</p>
  </div>
);
```

***

> *With React, we can render this JSX directly to the HTML DOM using React's rendering API known as ReactDOM.*

> *ReactDOM offers a simple method to render React elements to the DOM which looks like this:*

`ReactDOM.render(componentToRender, targetNode)`

* the first argument is the React element or component that you want to render,
* and the second argument is the DOM node that you want to render the component to.

> *ReactDOM.render() must be called after the JSX element declarations, just like how you must declare variables before using them.*

> *key difference in JSX is that you can no longer use the word class to define HTML classes.*

* — -> This is because class is a reserved word in JavaScript. Instead, JSX uses className

> *the naming convention for all HTML attributes and event references in JSX become camelCase*

> *a click event in JSX is onClick, instead of onclick. Likewise, onchange becomes onChange. While this is a subtle difference, it is an important one to keep in mind moving forward.*

#### Apply a class of myDiv to the div provided in the JSX code.

* The constant JSX should return a div element.
* The div should have a class of myDiv.

```
const JSX = (
  <div>
    <h1>Add a class to this div</h1>
  </div>
);
```

#### Ans:

```
const JSX = (
  <div className="myDiv">
    <h1>Add a class to this div</h1>
  </div>
);
```

#### React: Learn About Self-Closing JSX Tags

-Another important way in which JSX differs from HTML is in the idea of the self-closing tag.

> *In HTML, almost all tags have both an opening and closing tag:* `<div></div>;` *the closing tag always has a forward slash before the tag name that you are closing.*

> *there are special instances in HTML called “self-closing tags”, or tags that don't require both an opening and closing tag before another tag can start.*

> *For example the line-break tag can be written as* `<br>` *or as* `<br />,` *but should never be written as* `<br></br>`*, since it doesn't contain any content.*

> *In JSX, the rules are a little different. Any JSX element can be written with a self-closing tag, and every element must be closed.*\
> \&#xNAN;*The line-break tag, for example, must always be written as* `<br />` *in order to be valid JSX that can be transpiled.*\
> \&#xNAN;*A* `<div>`*, on the other hand, can be written as* `<div />`*or*`<div></div>`*.*\
> \&#xNAN;*The difference is that in the first syntax version there is no way to include anything in the* `<div />`*.*

#### Fix the errors in the code editor so that it is valid JSX and successfully transpiles. Make sure you don't change any of the content — you only need to close tags where they are needed.

```
const JSX = (
  <div>
    <h2>Welcome to React!</h2> <br >
    <p>Be sure to close all tags!</p>
    <hr >
  </div>
);
```

#### Ans:

```
const JSX = (
  <div>
    <h2>Welcome to React!</h2> <br />
    <p>Be sure to close all tags!</p>
    <hr />
  </div>
);
```

***

#### React: Create a Stateless Functional Component

> *There are two ways to create a React component. The first way is to use a JavaScript function.*

> *Defining a component in this way creates a stateless functional component.*

> *think of a stateless component as one that can receive data and render it, but does not manage or track changes to that data.*

**To create a component with a function, you simply write a JavaScript function that returns either JSX or null**

* React requires your function name to begin with a capital letter.

> *Here's an example of a stateless functional component that assigns an HTML class in JSX:*

```
// After being transpiled, the <div> will have a CSS class of 'customClass'
const DemoComponent = function() {
  return (
    <div className='customClass' />
  );
};
```

> *Because a JSX component represents HTML, you could put several components together to create a more complex HTML page.*

#### The code editor has a function called MyComponent. Complete this function so it returns a single div element which contains some string of text.

Note: The text is considered a child of the div element, so you will not be able to use a self-closing tag.

```
const MyComponent = function() {
  // Change code below this line

  // Change code above this line
}
```

#### ANS:

```
const MyComponent = function() {
  // Change code below this line

return (
   <div> Some Text </div >
  );

  // Change code above this line
};
```

***

#### React: Create a React Component

> *The other way to define a React component is with the ES6 class syntax. In the following example, Kitten extends React.Component:*

```
class Kitten extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <h1>Hi</h1>
    );
  }
}
```

> *This creates an ES6 class Kitten which extends the React.Component class.*

> *So the Kitten class now has access to many useful React features, such as local state and lifecycle hooks.*

> *Also notice the Kitten class has a constructor defined within it that calls super()*

> *It uses super() to call the constructor of the parent class, in this case React.Component*

> *The constructor is a special method used during the initialization of objects that are created with the class keyword. It is best practice to call a component's constructor with super, and pass props to both.*

> *This makes sure the component is initialized properly. For now, know that it is standard for this code to be included.*

#### MyComponent is defined in the code editor using class syntax. Finish writing the render method so it returns a div element that contains an h1 with the text Hello React!.

```
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    // Change code below this line

    // Change code above this line
  }
};
```

#### ANS:

```
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    // Change code below this line
 return (
   <div>
      <h1>Hello React!</h1>
      </div>
    );

    // Change code above this line
  }
};
```

***

#### React: Create a Component with Composition

> *Imagine you are building an App and have created three components, a Navbar, Dashboard, and Footer.*

> *To compose these components together, you could create an App parent component which renders each of these three components as children. To render a component as a child in a React component, you include the component name written as a custom HTML tag in the JSX.*

* For example, in the render method you could write:

```
return (
 <App>
  <Navbar />
  <Dashboard />
  <Footer />
 </App>
)
```

> *When React encounters a custom HTML tag that references another component (a component name wrapped in < /> like in this example), it renders the markup for that component in the location of the tag. This should illustrate the parent/child relationship between the App component and the Navbar, Dashboard, and Footer.*

#### Challenge:

> *In the code editor, there is a simple functional component called ChildComponent and a class component called ParentComponent. Compose the two together by rendering the ChildComponent within the ParentComponent. Make sure to close the ChildComponent tag with a forward slash.*

* Note:**ChildComponent is defined with an ES6 arrow function because this is a very common practice when using React**.
* However, know that this is just a function.

```
const ChildComponent = () => {
  return (
    <div>
      <p>I am the child</p>
    </div>
  );
};

class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <h1>I am the parent</h1>
        { /* Change code below this line */ }

        { /* Change code above this line */ }
      </div>
    );
  }
};
```

⌛The React component should return a single div element.\
⌛The component should return two nested elements.\
⌛The component should return the ChildComponent as its second child.

#### Ans:

```
const ChildComponent = () => {
  return (
    <div>
      <p>I am the child</p>
    </div>
  );
};

class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        <h1>I am the parent</h1>
        { /* Change code below this line */ }

        { /* Change code above this line */ }
      </div>
    );
  }
};
```

#### More Examples:

For more content follow me on GitHub:

[**bgoonz - Overview**\
\&#xNAN;*Web Developer, Electrical Engineer https://bryanguner.medium.com/ https://portfolio42.netlify.app/…*&#x67;ithub.com](https://github.com/bgoonz)

*More content at* [*plainenglish.io*](http://plainenglish.io/)

By [Bryan Guner](https://medium.com/@bryanguner) on [May 19, 2021](https://medium.com/p/8021738aa1ad).

[Canonical link](https://medium.com/@bryanguner/introduction-to-react-for-complete-beginners-8021738aa1ad)

Exported from [Medium](https://medium.com) on May 23, 2021.

## Snippets:

Renders an accordion menu with multiple collapsible content elements.

* Define an `AccordionItem` component, that renders a `<button>` which is used to update the component and notify its parent via the `handleClick` callback.
* Use the `isCollapsed` prop in `AccordionItem` to determine its appearance and set an appropriate `className`.
* Define an `Accordion` component that uses the `useState()` hook to initialize the value of the `bindIndex` state variable to `defaultIndex`.
* Filter `children` to remove unnecessary nodes except for `AccordionItem` by identifying the function's name.
* Use `Array.prototype.map()` on the collected nodes to render the individual collapsible elements.
* Define `changeItem`, which will be executed when clicking an `AccordionItem`'s `<button>`.
* `changeItem` executes the passed callback, `onItemClick`, and updates `bindIndex` based on the clicked element.

```
.accordion-item.collapsed {
  display: none;
}
.accordion-item.expanded {
  display: block;
}
.accordion-button {
  display: block;
  width: 100%;
}
```

````js

const AccordionItem = ({ label, isCollapsed, handleClick, children }) =&gt; {
  return (
    &lt;&gt;
      &lt;button className=&quot;accordion-button&quot; onClick={handleClick}&gt;
        {label}
      &lt;/button&gt;
      &lt;div
        className={`accordion-item ${isCollapsed ? &quot;collapsed&quot; : &quot;expanded&quot;}`}
        aria-expanded={isCollapsed}
      &gt;
        {children}
      &lt;/div&gt;
    &lt;/&gt;
  );
};

const Accordion = ({ defaultIndex, onItemClick, children }) =&gt; {
const [bindIndex, setBindIndex] = React.useState(defaultIndex);

const changeItem = (itemIndex) =&gt; {
if (typeof onItemClick === &quot;function&quot;) onItemClick(itemIndex);
if (itemIndex !== bindIndex) setBindIndex(itemIndex);
};
const items = children.filter((item) =&gt; item.type.name === &quot;AccordionItem&quot;);

return (
&lt;&gt;
{items.map(({ props }) =&gt; (
&lt;AccordionItem
isCollapsed={bindIndex !== props.index}
label={props.label}
handleClick={() =&gt; changeItem(props.index)}
children={props.children}
/&gt;
))}
&lt;/&gt;
);
};



<hr />

```js

ReactDOM.render(
  &lt;Accordion defaultIndex=&quot;1&quot; onItemClick={console.log}&gt;
    &lt;AccordionItem label=&quot;A&quot; index=&quot;1&quot;&gt;
      Lorem ipsum
    &lt;/AccordionItem&gt;
    &lt;AccordionItem label=&quot;B&quot; index=&quot;2&quot;&gt;
      Dolor sit amet
    &lt;/AccordionItem&gt;
  &lt;/Accordion&gt;,
  document.getElementById(&quot;root&quot;)
);
````

***

Renders an alert component with `type` prop.

* Use the `useState()` hook to create the `isShown` and `isLeaving` state variables and set both to `false` initially.
* Define `timeoutId` to keep the timer instance for clearing on component unmount.
* Use the `useEffect()` hook to update the value of `isShown` to `true` and clear the interval by using `timeoutId` when the component is unmounted.
* Define a `closeAlert` function to set the component as removed from the DOM by displaying a fading out animation and set `isShown` to `false` via `setTimeout()`.

```
@keyframes leave {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
.alert {
  padding: 0.75rem 0.5rem;
  margin-bottom: 0.5rem;
  text-align: left;
  padding-right: 40px;
  border-radius: 4px;
  font-size: 16px;
  position: relative;
}
.alert.warning {
  color: #856404;
  background-color: #fff3cd;
  border-color: #ffeeba;
}
.alert.error {
  color: #721c24;
  background-color: #f8d7da;
  border-color: #f5c6cb;
}
.alert.leaving {
  animation: leave 0.5s forwards;
}
.alert .close {
  position: absolute;
  top: 0;
  right: 0;
  padding: 0 0.75rem;
  color: #333;
  border: 0;
  height: 100%;
  cursor: pointer;
  background: none;
  font-weight: 600;
  font-size: 16px;
}
.alert .close:after {
  content: "x";
}
```

````js

const Alert = ({ isDefaultShown = false, timeout = 250, type, message }) =&gt; {
  const [isShown, setIsShown] = React.useState(isDefaultShown);
  const [isLeaving, setIsLeaving] = React.useState(false);

let timeoutId = null;

React.useEffect(() =&gt; {
setIsShown(true);
return () =&gt; {
clearTimeout(timeoutId);
};
}, [isDefaultShown, timeout, timeoutId]);

const closeAlert = () =&gt; {
setIsLeaving(true);
timeoutId = setTimeout(() =&gt; {
setIsLeaving(false);
setIsShown(false);
}, timeout);
};

return (
isShown &amp;&amp; (
&lt;div
className={`alert ${type} ${isLeaving ? &quot;leaving&quot; : &quot;&quot;}`}
role=&quot;alert&quot;
&gt;
&lt;button className=&quot;close&quot; onClick={closeAlert} /&gt;
{message}
&lt;/div&gt;
)
);
};



<hr />

```js

ReactDOM.render(
  &lt;Alert type=&quot;info&quot; message=&quot;This is info&quot; /&gt;,
  document.getElementById(&quot;root&quot;)
);
````

***

Renders a string as plaintext, with URLs converted to appropriate link elements.

* Use `String.prototype.split()` and `String.prototype.match()` with a regular expression to find URLs in a string.
* Return matched URLs rendered as `<a>` elements, dealing with missing protocol prefixes if necessary.
* Render the rest of the string as plaintext.

```js

const AutoLink = ({ text }) =&gt; {
  const delimiter =
    /((?:https?:\/\/)?(?:(?:[a-z0-9]?(?:[a-z0-9\-]{1,61}[a-z0-9])?\.[^\.|\s])+[a-z\.]*[a-z]+|(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})(?::\d{1,5})*[a-z0-9.,_\/~#&amp;=;%+?\-\\(\\)]*)/gi;

return (
&lt;&gt;
{text.split(delimiter).map((word) =&gt; {
const match = word.match(delimiter);
if (match) {
const url = match[0];
return (
&lt;a href={url.startsWith(&quot;http&quot;) ? url : `http://${url}`}&gt;{url}&lt;/a&gt;
);
}
return word;
})}
&lt;/&gt;
);
};
```

***

```js

ReactDOM.render(
  &lt;AutoLink text=&quot;foo bar baz http://example.org bar&quot; /&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

Renders a link formatted to call a phone number (`tel:` link).

* Use `phone` to create a `<a>` element with an appropriate `href` attribute.
* Render the link with `children` as its content.

```js

const Callto = ({ phone, children }) =&gt; {
  return &lt;a href={`tel:${phone}`}&gt;{children}&lt;/a&gt;;
};
```

***

```js

ReactDOM.render(
  &lt;Callto phone=&quot;+302101234567&quot;&gt;Call me!&lt;/Callto&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

Renders a carousel component.

* Use the `useState()` hook to create the `active` state variable and give it a value of `0` (index of the first item).
* Use the `useEffect()` hook to update the value of `active` to the index of the next item, using `setTimeout`.
* Compute the `className` for each carousel item while mapping over them and applying it accordingly.
* Render the carousel items using `React.cloneElement()` and pass down `...rest` along with the computed `className`.

```
.carousel {
  position: relative;
}
.carousel-item {
  position: absolute;
  visibility: hidden;
}
.carousel-item.visible {
  visibility: visible;
}
```

````js

const Carousel = ({ carouselItems, ...rest }) =&gt; {
  const [active, setActive] = React.useState(0);
  let scrollInterval = null;

React.useEffect(() =&gt; {
scrollInterval = setTimeout(() =&gt; {
setActive((active + 1) % carouselItems.length);
}, 2000);
return () =&gt; clearTimeout(scrollInterval);
});

return (
&lt;div className=&quot;carousel&quot;&gt;
{carouselItems.map((item, index) =&gt; {
const activeClass = active === index ? &quot; visible&quot; : &quot;&quot;;
return React.cloneElement(item, {
...rest,
className: `carousel-item${activeClass}`,
});
})}
&lt;/div&gt;
);
};



<hr />

```js

ReactDOM.render(
  &lt;Carousel
    carouselItems={[
      &lt;div&gt;carousel item 1&lt;/div&gt;,
      &lt;div&gt;carousel item 2&lt;/div&gt;,
      &lt;div&gt;carousel item 3&lt;/div&gt;,
    ]}
  /&gt;,
  document.getElementById(&quot;root&quot;)
);
````

***

Renders a component with collapsible content.

* Use the `useState()` hook to create the `isCollapsed` state variable with an initial value of `collapsed`.
* Use the `<button>` to change the component's `isCollapsed` state and the content of the component, passed down via `children`.
* Determine the appearance of the content, based on `isCollapsed` and apply the appropriate `className`.
* Update the value of the `aria-expanded` attribute based on `isCollapsed` to make the component accessible.

```
.collapse-button {
  display: block;
  width: 100%;
}
.collapse-content.collapsed {
  display: none;
}
.collapsed-content.expanded {
  display: block;
}
```

````js

const Collapse = ({ collapsed, children }) =&gt; {
  const [isCollapsed, setIsCollapsed] = React.useState(collapsed);

return (
&lt;&gt;
&lt;button
className=&quot;collapse-button&quot;
onClick={() =&gt; setIsCollapsed(!isCollapsed)}
&gt;
{isCollapsed ? &quot;Show&quot; : &quot;Hide&quot;} content
&lt;/button&gt;
&lt;div
className={`collapse-content ${isCollapsed ? &quot;collapsed&quot; : &quot;expanded&quot;}`}
aria-expanded={isCollapsed}
&gt;
{children}
&lt;/div&gt;
&lt;/&gt;
);
};



<hr />

```js

ReactDOM.render(
  &lt;Collapse&gt;
    &lt;h1&gt;This is a collapse&lt;/h1&gt;
    &lt;p&gt;Hello world!&lt;/p&gt;
  &lt;/Collapse&gt;,
  document.getElementById(&quot;root&quot;)
);
````

***

Renders a controlled `<input>` element that uses a callback function to inform its parent about value updates.

* Use the `value` passed down from the parent as the controlled input field's value.
* Use the `onChange` event to fire the `onValueChange` callback and send the new value to the parent.
* The parent must update the input field's `value` prop in order for its value to change on user input.

```js

const ControlledInput = ({ value, onValueChange, ...rest }) =&gt; {
  return (
    &lt;input
      value={value}
      onChange={({ target: { value } }) =&gt; onValueChange(value)}
      {...rest}
    /&gt;
  );
};
```

***

```js

const Form = () =&gt; {
  const [value, setValue] = React.useState(&quot;&quot;);

return (
&lt;ControlledInput
type=&quot;text&quot;
placeholder=&quot;Insert some text here...&quot;
value={value}
onValueChange={setValue}
/&gt;
);
};

ReactDOM.render(&lt;Form /&gt;, document.getElementById(&quot;root&quot;));
```

***

Renders a countdown timer that prints a message when it reaches zero.

* 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 `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.

```js

const CountDown = ({ hours = 0, minutes = 0, seconds = 0 }) =&gt; {
  const [paused, setPaused] = React.useState(false);
  const [over, setOver] = React.useState(false);
  const [[h, m, s], setTime] = React.useState([hours, minutes, seconds]);

const tick = () =&gt; {
if (paused || over) return;
if (h === 0 &amp;&amp; m === 0 &amp;&amp; s === 0) setOver(true);
else if (m === 0 &amp;&amp; s === 0) {
setTime([h - 1, 59, 59]);
} else if (s == 0) {
setTime([h, m - 1, 59]);
} else {
setTime([h, m, s - 1]);
}
};

const reset = () =&gt; {
setTime([parseInt(hours), parseInt(minutes), parseInt(seconds)]);
setPaused(false);
setOver(false);
};

React.useEffect(() =&gt; {
const timerID = setInterval(() =&gt; tick(), 1000);
return () =&gt; clearInterval(timerID);
});

return (
&lt;div&gt;
&lt;p&gt;{`${h.toString().padStart(2, &quot;0&quot;)}:${m.toString().padStart(2, &quot;0&quot;)}:${s .toString() .padStart(2, &quot;0&quot;)}`}&lt;/p&gt;
&lt;div&gt;{over ? &quot;Time&#39;s up!&quot; : &quot;&quot;}&lt;/div&gt;
&lt;button onClick={() =&gt; setPaused(!paused)}&gt;
{paused ? &quot;Resume&quot; : &quot;Pause&quot;}
&lt;/button&gt;
&lt;button onClick={() =&gt; reset()}&gt;Restart&lt;/button&gt;
&lt;/div&gt;
);
};
```

***

```js

ReactDOM.render(
  &lt;CountDown hours={1} minutes={45} /&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

Renders a list of elements from an array of primitives.

* Use the value of the `isOrdered` prop to conditionally render an `<ol>` or a `<ul>` list.
* Use `Array.prototype.map()` to render every item in `data` as a `<li>` element with an appropriate `key`.

```js

const DataList = ({ isOrdered = false, data }) =&gt; {
  const list = data.map((val, i) =&gt; &lt;li key={`${i}_${val}`}&gt;{val}&lt;/li&gt;);
  return isOrdered ? &lt;ol&gt;{list}&lt;/ol&gt; : &lt;ul&gt;{list}&lt;/ul&gt;;
};
```

***

```js

const names = [&quot;John&quot;, &quot;Paul&quot;, &quot;Mary&quot;];
ReactDOM.render(&lt;DataList data={names} /&gt;, document.getElementById(&quot;root&quot;));
ReactDOM.render(
  &lt;DataList data={names} isOrdered /&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

Renders a table with rows dynamically created from an array of primitives.

* Render a `<table>` element with two columns (`ID` and `Value`).
* Use `Array.prototype.map()` to render every item in `data` as a `<tr>` element with an appropriate `key`.

```js

const DataTable = ({ data }) =&gt; {
  return (
    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;ID&lt;/th&gt;
          &lt;th&gt;Value&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        {data.map((val, i) =&gt; (
          &lt;tr key={`${i}_${val}`}&gt;
            &lt;td&gt;{i}&lt;/td&gt;
            &lt;td&gt;{val}&lt;/td&gt;
          &lt;/tr&gt;
        ))}
      &lt;/tbody&gt;
    &lt;/table&gt;
  );
};
```

***

```js

const people = [&quot;John&quot;, &quot;Jesse&quot;];
ReactDOM.render(&lt;DataTable data={people} /&gt;, document.getElementById(&quot;root&quot;));
```

***

Renders a file drag and drop component for a single file.

* Create a ref, called `dropRef` and bind it to the component's wrapper.
* Use the `useState()` hook to create the `drag` and `filename` variables, initialized to `false` and `''` respectively.
* The variables `dragCounter` and `drag` are used to determine if a file is being dragged, while `filename` is used to store the dropped file's name.
* Create the `handleDrag`, `handleDragIn`, `handleDragOut` and `handleDrop` methods to handle drag and drop functionality.
* `handleDrag` prevents the browser from opening the dragged file, `handleDragIn` and `handleDragOut` handle the dragged file entering and exiting the component, while `handleDrop` handles the file being dropped and passes it to `onDrop`.
* Use the `useEffect()` hook to handle each of the drag and drop events using the previously created methods.

```
.filedrop {
  min-height: 120px;
  border: 3px solid #d3d3d3;
  text-align: center;
  font-size: 24px;
  padding: 32px;
  border-radius: 4px;
}
.filedrop.drag {
  border: 3px dashed #1e90ff;
}
.filedrop.ready {
  border: 3px solid #32cd32;
}
```

````js

const FileDrop = ({ onDrop }) =&gt; {
  const [drag, setDrag] = React.useState(false);
  const [filename, setFilename] = React.useState(&quot;&quot;);
  let dropRef = React.createRef();
  let dragCounter = 0;

const handleDrag = (e) =&gt; {
e.preventDefault();
e.stopPropagation();
};

const handleDragIn = (e) =&gt; {
e.preventDefault();
e.stopPropagation();
dragCounter++;
if (e.dataTransfer.items &amp;&amp; e.dataTransfer.items.length &gt; 0) setDrag(true);
};

const handleDragOut = (e) =&gt; {
e.preventDefault();
e.stopPropagation();
dragCounter--;
if (dragCounter === 0) setDrag(false);
};

const handleDrop = (e) =&gt; {
e.preventDefault();
e.stopPropagation();
setDrag(false);
if (e.dataTransfer.files &amp;&amp; e.dataTransfer.files.length &gt; 0) {
onDrop(e.dataTransfer.files[0]);
setFilename(e.dataTransfer.files[0].name);
e.dataTransfer.clearData();
dragCounter = 0;
}
};

React.useEffect(() =&gt; {
let div = dropRef.current;
div.addEventListener(&quot;dragenter&quot;, handleDragIn);
div.addEventListener(&quot;dragleave&quot;, handleDragOut);
div.addEventListener(&quot;dragover&quot;, handleDrag);
div.addEventListener(&quot;drop&quot;, handleDrop);
return () =&gt; {
div.removeEventListener(&quot;dragenter&quot;, handleDragIn);
div.removeEventListener(&quot;dragleave&quot;, handleDragOut);
div.removeEventListener(&quot;dragover&quot;, handleDrag);
div.removeEventListener(&quot;drop&quot;, handleDrop);
};
});

return (
&lt;div
ref={dropRef}
className={
drag ? &quot;filedrop drag&quot; : filename ? &quot;filedrop ready&quot; : &quot;filedrop&quot;
}
&gt;
{filename &amp;&amp; !drag ? &lt;div&gt;{filename}&lt;/div&gt; : &lt;div&gt;Drop a file here!&lt;/div&gt;}
&lt;/div&gt;
);
};



<hr />

```js

ReactDOM.render(
  &lt;FileDrop onDrop={console.log} /&gt;,
  document.getElementById(&quot;root&quot;)
);
````

***

Renders a textarea component with a character limit.

* Use the `useState()` hook to create the `content` state variable and set its value to that of `value` prop, trimmed down to `limit` characters.
* Create a method `setFormattedContent`, which trims the content down to `limit` characters and memoize it, using the `useCallback()` hook.
* Bind the `onChange` event of the `<textarea>` to call `setFormattedContent` with the value of the fired event.

```js

const LimitedTextarea = ({ rows, cols, value, limit }) =&gt; {
  const [content, setContent] = React.useState(value.slice(0, limit));

const setFormattedContent = React.useCallback(
(text) =&gt; {
setContent(text.slice(0, limit));
},
[limit, setContent]
);

return (
&lt;&gt;
&lt;textarea
rows={rows}
cols={cols}
onChange={(event) =&gt; setFormattedContent(event.target.value)}
value={content}
/&gt;
&lt;p&gt;
{content.length}/{limit}
&lt;/p&gt;
&lt;/&gt;
);
};
```

***

```js

ReactDOM.render(
  &lt;LimitedTextarea limit={32} value=&quot;Hello!&quot; /&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

Renders a textarea component with a word limit.

* Use the `useState()` hook to create a state variable, containing `content` and `wordCount`, using the `value` prop and `0` as the initial values respectively.
* Use the `useCallback()` hooks to create a memoized function, `setFormattedContent`, that uses `String.prototype.split()` to turn the input into an array of words.
* Check if the result of applying `Array.prototype.filter()` combined with `Boolean` has a `length` longer than `limit` and, if so, trim the input, otherwise return the raw input, updating state accordingly in both cases.
* Use the `useEffect()` hook to call the `setFormattedContent` method on the value of the `content` state variable during the initial render.
* Bind the `onChange` event of the `<textarea>` to call `setFormattedContent` with the value of `event.target.value`.

```js

const LimitedWordTextarea = ({ rows, cols, value, limit }) =&gt; {
  const [{ content, wordCount }, setContent] = React.useState({
    content: value,
    wordCount: 0,
  });

const setFormattedContent = React.useCallback(
(text) =&gt; {
let words = text.split(&quot; &quot;).filter(Boolean);
if (words.length &gt; limit) {
setContent({
content: words.slice(0, limit).join(&quot; &quot;),
wordCount: limit,
});
} else {
setContent({ content: text, wordCount: words.length });
}
},
[limit, setContent]
);

React.useEffect(() =&gt; {
setFormattedContent(content);
}, []);

return (
&lt;&gt;
&lt;textarea
rows={rows}
cols={cols}
onChange={(event) =&gt; setFormattedContent(event.target.value)}
value={content}
/&gt;
&lt;p&gt;
{wordCount}/{limit}
&lt;/p&gt;
&lt;/&gt;
);
};
```

***

```js

ReactDOM.render(
  &lt;LimitedWordTextarea limit={5} value=&quot;Hello there!&quot; /&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

Renders a spinning loader component.

* Render an SVG, whose `height` and `width` are determined by the `size` prop.
* Use CSS to animate the SVG, creating a spinning animation.

```
.loader {
  animation: rotate 2s linear infinite;
}
@keyframes rotate {
  100% {
    transform: rotate(360deg);
  }
}
.loader circle {
  animation: dash 1.5s ease-in-out infinite;
}
@keyframes dash {
  0% {
    stroke-dasharray: 1, 150;
    stroke-dashoffset: 0;
  }
  50% {
    stroke-dasharray: 90, 150;
    stroke-dashoffset: -35;
  }
  100% {
    stroke-dasharray: 90, 150;
    stroke-dashoffset: -124;
  }
}
```

````js

const Loader = ({ size }) =&gt; {
  return (
    &lt;svg
      className=&quot;loader&quot;
      xmlns=&quot;http://www.w3.org/2000/svg&quot;
      width={size}
      height={size}
      viewBox=&quot;0 0 24 24&quot;
      fill=&quot;none&quot;
      stroke=&quot;currentColor&quot;
      strokeWidth=&quot;2&quot;
      strokeLinecap=&quot;round&quot;
      strokeLinejoin=&quot;round&quot;
    &gt;
      &lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;10&quot; /&gt;
    &lt;/svg&gt;
  );
};



<hr />

```js

ReactDOM.render(&lt;Loader size={24} /&gt;, document.getElementById(&quot;root&quot;));
````

***

Renders a link formatted to send an email (`mailto:` link).

* Use the `email`, `subject` and `body` props to create a `<a>` element with an appropriate `href` attribute.
* Use `encodeURIcomponent` to safely encode the `subject` and `body` into the link URL.
* Render the link with `children` as its content.

```js

const Mailto = ({ email, subject = &quot;&quot;, body = &quot;&quot;, children }) =&gt; {
  let params = subject || body ? &quot;?&quot; : &quot;&quot;;
  if (subject) params += `subject=${encodeURIComponent(subject)}`;
  if (body) params += `${subject ? &quot;&amp;&quot; : &quot;&quot;}body=${encodeURIComponent(body)}`;

return &lt;a href={`mailto:${email}${params}`}&gt;{children}&lt;/a&gt;;
};
```

***

```js

ReactDOM.render(
  &lt;Mailto email=&quot;foo@bar.baz&quot; subject=&quot;Hello &amp; Welcome&quot; body=&quot;Hello world!&quot;&gt;
    Mail me!
  &lt;/Mailto&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

Renders a table with rows dynamically created from an array of objects and a list of property names.

* Use `Object.keys()`, `Array.prototype.filter()`, `Array.prototype.includes()` and `Array.prototype.reduce()` to produce a `filteredData` array, containing all objects with the keys specified in `propertyNames`.
* Render a `<table>` element with a set of columns equal to the amount of values in `propertyNames`.
* Use `Array.prototype.map()` to render each value in the `propertyNames` array as a `<th>` element.
* Use `Array.prototype.map()` to render each object in the `filteredData` array as a `<tr>` element, containing a `<td>` for each key in the object.

*This component does not work with nested objects and will break if there are nested objects inside any of the properties specified in `propertyNames`*

```js

const MappedTable = ({ data, propertyNames }) =&gt; {
  let filteredData = data.map((v) =&gt;
    Object.keys(v)
      .filter((k) =&gt; propertyNames.includes(k))
      .reduce((acc, key) =&gt; ((acc[key] = v[key]), acc), {})
  );
  return (
    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          {propertyNames.map((val) =&gt; (
            &lt;th key={`h_${val}`}&gt;{val}&lt;/th&gt;
          ))}
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        {filteredData.map((val, i) =&gt; (
          &lt;tr key={`i_${i}`}&gt;
            {propertyNames.map((p) =&gt; (
              &lt;td key={`i_${i}_${p}`}&gt;{val[p]}&lt;/td&gt;
            ))}
          &lt;/tr&gt;
        ))}
      &lt;/tbody&gt;
    &lt;/table&gt;
  );
};
```

***

```js

const people = [
  { name: &quot;John&quot;, surname: &quot;Smith&quot;, age: 42 },
  { name: &quot;Adam&quot;, surname: &quot;Smith&quot;, gender: &quot;male&quot; },
];
const propertyNames = [&quot;name&quot;, &quot;surname&quot;, &quot;age&quot;];
ReactDOM.render(
  &lt;MappedTable data={people} propertyNames={propertyNames} /&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

Renders a Modal component, controllable through events.

* Define `keydownHandler`, a method which handles all keyboard events and is used to call `onClose` when the `Esc` key is pressed.
* Use the `useEffect()` hook to add or remove the `keydown` event listener to the `document`, calling `keydownHandler` for every event.
* Add a styled `<span>` element that acts as a close button, calling `onClose` when clicked.
* Use the `isVisible` prop passed down from the parent to determine if the modal should be displayed or not.
* To use the component, import `Modal` only once and then display it by passing a boolean value to the `isVisible` attribute.

```
.modal {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  width: 100%;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, 0.25);
  animation-name: appear;
  animation-duration: 300ms;
}
.modal-dialog {
  width: 100%;
  max-width: 550px;
  background: white;
  position: relative;
  margin: 0 20px;
  max-height: calc(100vh - 40px);
  text-align: left;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
  -webkit-animation-name: animatetop;
  -webkit-animation-duration: 0.4s;
  animation-name: slide-in;
  animation-duration: 0.5s;
}
.modal-header,
.modal-footer {
  display: flex;
  align-items: center;
  padding: 1rem;
}
.modal-header {
  border-bottom: 1px solid #dbdbdb;
  justify-content: space-between;
}
.modal-footer {
  border-top: 1px solid #dbdbdb;
  justify-content: flex-end;
}
.modal-close {
  cursor: pointer;
  padding: 1rem;
  margin: -1rem -1rem -1rem auto;
}
.modal-body {
  overflow: auto;
}
.modal-content {
  padding: 1rem;
}
@keyframes appear {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes slide-in {
  from {
    transform: translateY(-150px);
  }
  to {
    transform: translateY(0);
  }
}
```

````js

const Modal = ({ isVisible = false, title, content, footer, onClose }) =&gt; {
  const keydownHandler = ({ key }) =&gt; {
    switch (key) {
      case &quot;Escape&quot;:
        onClose();
        break;
      default:
    }
  };

React.useEffect(() =&gt; {
document.addEventListener(&quot;keydown&quot;, keydownHandler);
return () =&gt; document.removeEventListener(&quot;keydown&quot;, keydownHandler);
});

return !isVisible ? null : (
&lt;div className=&quot;modal&quot; onClick={onClose}&gt;
&lt;div className=&quot;modal-dialog&quot; onClick={(e) =&gt; e.stopPropagation()}&gt;
&lt;div className=&quot;modal-header&quot;&gt;
&lt;h3 className=&quot;modal-title&quot;&gt;{title}&lt;/h3&gt;
&lt;span className=&quot;modal-close&quot; onClick={onClose}&gt;
&amp;times;
&lt;/span&gt;
&lt;/div&gt;
&lt;div className=&quot;modal-body&quot;&gt;
&lt;div className=&quot;modal-content&quot;&gt;{content}&lt;/div&gt;
&lt;/div&gt;
{footer &amp;&amp; &lt;div className=&quot;modal-footer&quot;&gt;{footer}&lt;/div&gt;}
&lt;/div&gt;
&lt;/div&gt;
);
};



<hr />

```js

const App = () =&gt; {
  const [isModal, setModal] = React.useState(false);
  return (
    &lt;&gt;
      &lt;button onClick={() =&gt; setModal(true)}&gt;Click Here&lt;/button&gt;
      &lt;Modal
        isVisible={isModal}
        title=&quot;Modal Title&quot;
        content={&lt;p&gt;Add your content here&lt;/p&gt;}
        footer={&lt;button&gt;Cancel&lt;/button&gt;}
        onClose={() =&gt; setModal(false)}
      /&gt;
    &lt;/&gt;
  );
};

ReactDOM.render(&lt;App /&gt;, document.getElementById(&quot;root&quot;));
````

***

Renders a checkbox list that uses a callback function to pass its selected value/values to the parent component.

* 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 `<input type="checkbox">` elements, each one wrapped in a `<label>`, binding the `onClick` handler to the `toggle` function.

```js

const MultiselectCheckbox = ({ options, onChange }) =&gt; {
  const [data, setData] = React.useState(options);

const toggle = (index) =&gt; {
const newData = [...data];
newData.splice(index, 1, {
label: data[index].label,
checked: !data[index].checked,
});
setData(newData);
onChange(newData.filter((x) =&gt; x.checked));
};

return (
&lt;&gt;
{data.map((item, index) =&gt; (
&lt;label key={item.label}&gt;
&lt;input
readOnly
type=&quot;checkbox&quot;
checked={item.checked || false}
onClick={() =&gt; toggle(index)}
/&gt;
{item.label}
&lt;/label&gt;
))}
&lt;/&gt;
);
};
```

***

```js

const options = [{ label: &quot;Item One&quot; }, { label: &quot;Item Two&quot; }];

ReactDOM.render(
&lt;MultiselectCheckbox
options={options}
onChange={(data) =&gt; {
console.log(data);
}}
/&gt;,
document.getElementById(&quot;root&quot;)
);
```

***

Renders a password input field with a reveal button.

* Use the `useState()` hook to create the `shown` state variable and set its value to `false`.
* When the `<button>` is clicked, execute `setShown`, toggling the `type` of the `<input>` between `"text"` and `"password"`.

```js

const PasswordRevealer = ({ value }) =&gt; {
  const [shown, setShown] = React.useState(false);
  return (
    &lt;&gt;
      &lt;input type={shown ? &quot;text&quot; : &quot;password&quot;} value={value} /&gt;
      &lt;button onClick={() =&gt; setShown(!shown)}&gt;Show/Hide&lt;/button&gt;
    &lt;/&gt;
  );
};
```

***

```js

ReactDOM.render(&lt;PasswordRevealer /&gt;, document.getElementById(&quot;root&quot;));
```

***

Renders a button that animates a ripple effect when clicked.

* Use the `useState()` hook to create the `coords` and `isRippling` state variables for the pointer's coordinates and the animation state of the button respectively.
* Use a `useEffect()` hook to change the value of `isRippling` every time the `coords` state variable changes, starting the animation.
* Use `setTimeout()` in the previous hook to clear the animation after it's done playing.
* Use a `useEffect()` hook to reset `coords` whenever the `isRippling` state variable is `false.`
* Handle the `onClick` event by updating the `coords` state variable and calling the passed callback.

```
.ripple-button {
  border-radius: 4px;
  border: none;
  margin: 8px;
  padding: 14px 24px;
  background: #1976d2;
  color: #fff;
  overflow: hidden;
  position: relative;
  cursor: pointer;
}
.ripple-button > .ripple {
  width: 20px;
  height: 20px;
  position: absolute;
  background: #63a4ff;
  display: block;
  content: "";
  border-radius: 9999px;
  opacity: 1;
  animation: 0.9s ease 1 forwards ripple-effect;
}
@keyframes ripple-effect {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(10);
    opacity: 0.375;
  }
  100% {
    transform: scale(35);
    opacity: 0;
  }
}
.ripple-button > .content {
  position: relative;
  z-index: 2;
}
```

````js

const RippleButton = ({ children, onClick }) =&gt; {
  const [coords, setCoords] = React.useState({ x: -1, y: -1 });
  const [isRippling, setIsRippling] = React.useState(false);

React.useEffect(() =&gt; {
if (coords.x !== -1 &amp;&amp; coords.y !== -1) {
setIsRippling(true);
setTimeout(() =&gt; setIsRippling(false), 300);
} else setIsRippling(false);
}, [coords]);

React.useEffect(() =&gt; {
if (!isRippling) setCoords({ x: -1, y: -1 });
}, [isRippling]);

return (
&lt;button
className=&quot;ripple-button&quot;
onClick={(e) =&gt; {
const rect = e.target.getBoundingClientRect();
setCoords({ x: e.clientX - rect.left, y: e.clientY - rect.top });
onClick &amp;&amp; onClick(e);
}}
&gt;
{isRippling ? (
&lt;span
className=&quot;ripple&quot;
style={{
            left: coords.x,
            top: coords.y,
          }}
/&gt;
) : (
&quot;&quot;
)}
&lt;span className=&quot;content&quot;&gt;{children}&lt;/span&gt;
&lt;/button&gt;
);
};



<hr />

```js

ReactDOM.render(
  &lt;RippleButton onClick={(e) =&gt; console.log(e)}&gt;Click me&lt;/RippleButton&gt;,
  document.getElementById(&quot;root&quot;)
);
````

***

Renders an uncontrolled `<select>` element that uses a callback function to pass its value to the parent component.

* Use the the `selectedValue` prop as the `defaultValue` of the `<select>` element to set its initial value..
* Use the `onChange` event to fire the `onValueChange` callback and send the new value to the parent.
* Use `Array.prototype.map()` on the `values` array to create an `<option>` element for each passed value.
* Each item in `values` must be a 2-element array, where the first element is the `value` of the item and the second one is the displayed text for it.

```js

const Select = ({ values, onValueChange, selectedValue, ...rest }) =&gt; {
  return (
    &lt;select
      defaultValue={selectedValue}
      onChange={({ target: { value } }) =&gt; onValueChange(value)}
      {...rest}
    &gt;
      {values.map(([value, text]) =&gt; (
        &lt;option key={value} value={value}&gt;
          {text}
        &lt;/option&gt;
      ))}
    &lt;/select&gt;
  );
};
```

***

```js

const choices = [
  [&quot;grapefruit&quot;, &quot;Grapefruit&quot;],
  [&quot;lime&quot;, &quot;Lime&quot;],
  [&quot;coconut&quot;, &quot;Coconut&quot;],
  [&quot;mango&quot;, &quot;Mango&quot;],
];
ReactDOM.render(
  &lt;Select
    values={choices}
    selectedValue=&quot;lime&quot;
    onValueChange={(val) =&gt; console.log(val)}
  /&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

Renders an uncontrolled range input element that uses a callback function to pass its value to the parent component.

* Set the `type` of the `<input>` element to `"range"` to create a slider.
* Use the `defaultValue` passed down from the parent as the uncontrolled input field's initial value.
* Use the `onChange` event to fire the `onValueChange` callback and send the new value to the parent.

```js

const Slider = ({
  min = 0,
  max = 100,
  defaultValue,
  onValueChange,
  ...rest
}) =&gt; {
  return (
    &lt;input
      type=&quot;range&quot;
      min={min}
      max={max}
      defaultValue={defaultValue}
      onChange={({ target: { value } }) =&gt; onValueChange(value)}
      {...rest}
    /&gt;
  );
};
```

***

```js

ReactDOM.render(
  &lt;Slider onValueChange={(val) =&gt; console.log(val)} /&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

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 `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 `<Star>` components.
* Handle the `onMouseOver` and `onMouseLeave` events of the wrapping element using `hoverOver` and the `onClick` event using `setRating`.

```
.star {
  color: #ff9933;
  cursor: pointer;
}
```

````js

const Star = ({ marked, starId }) =&gt; {
  return (
    &lt;span data-star-id={starId} className=&quot;star&quot; role=&quot;button&quot;&gt;
      {marked ? &quot;\u2605&quot; : &quot;\u2606&quot;}
    &lt;/span&gt;
  );
};

const StarRating = ({ value }) =&gt; {
const [rating, setRating] = React.useState(parseInt(value) || 0);
const [selection, setSelection] = React.useState(0);

const hoverOver = (event) =&gt; {
let val = 0;
if (event &amp;&amp; event.target &amp;&amp; event.target.getAttribute(&quot;data-star-id&quot;))
val = event.target.getAttribute(&quot;data-star-id&quot;);
setSelection(val);
};
return (
&lt;div
onMouseOut={() =&gt; hoverOver(null)}
onClick={(e) =&gt;
setRating(e.target.getAttribute(&quot;data-star-id&quot;) || rating)
}
onMouseOver={hoverOver}
&gt;
{Array.from({ length: 5 }, (v, i) =&gt; (
&lt;Star
starId={i + 1}
key={`star_${i + 1}`}
marked={selection ? selection &gt;= i + 1 : rating &gt;= i + 1}
/&gt;
))}
&lt;/div&gt;
);
};



<hr />

```js

ReactDOM.render(&lt;StarRating value={2} /&gt;, document.getElementById(&quot;root&quot;));
````

***

Renders a tabbed menu and view component.

* Define a `Tabs` component that uses the `useState()` hook to initialize the value of the `bindIndex` state variable to `defaultIndex`.
* Define a `TabItem` component and filter `children` passed to the `Tabs` component to remove unnecessary nodes except for `TabItem` by identifying the function's name.
* Define `changeTab`, which will be executed when clicking a `<button>` from the menu.
* `changeTab` executes the passed callback, `onTabClick`, and updates `bindIndex` based on the clicked element.
* Use `Array.prototype.map()` on the collected nodes to render the menu and view of the tabs, using the value of `binIndex` to determine the active tab and apply the correct `className`.

```
.tab-menu > button {
  cursor: pointer;
  padding: 8px 16px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
}
.tab-menu > button.focus {
  border-bottom: 2px solid #007bef;
}
.tab-menu > button:hover {
  border-bottom: 2px solid #007bef;
}
.tab-content {
  display: none;
}
.tab-content.selected {
  display: block;
}
```

````js

const TabItem = (props) =&gt; &lt;div {...props} /&gt;;

const Tabs = ({ defaultIndex = 0, onTabClick, children }) =&gt; {
const [bindIndex, setBindIndex] = React.useState(defaultIndex);
const changeTab = (newIndex) =&gt; {
if (typeof onItemClick === &quot;function&quot;) onItemClick(itemIndex);
setBindIndex(newIndex);
};
const items = children.filter((item) =&gt; item.type.name === &quot;TabItem&quot;);

return (
&lt;div className=&quot;wrapper&quot;&gt;
&lt;div className=&quot;tab-menu&quot;&gt;
{items.map(({ props: { index, label } }) =&gt; (
&lt;button
key={`tab-btn-${index}`}
onClick={() =&gt; changeTab(index)}
className={bindIndex === index ? &quot;focus&quot; : &quot;&quot;}
&gt;
{label}
&lt;/button&gt;
))}
&lt;/div&gt;
&lt;div className=&quot;tab-view&quot;&gt;
{items.map(({ props }) =&gt; (
&lt;div
{...props}
className={`tab-content ${ bindIndex === props.index ? &quot;selected&quot; : &quot;&quot; }`}
key={`tab-content-${props.index}`}
/&gt;
))}
&lt;/div&gt;
&lt;/div&gt;
);
};



<hr />

```js

ReactDOM.render(
  &lt;Tabs defaultIndex=&quot;1&quot; onTabClick={console.log}&gt;
    &lt;TabItem label=&quot;A&quot; index=&quot;1&quot;&gt;
      Lorem ipsum
    &lt;/TabItem&gt;
    &lt;TabItem label=&quot;B&quot; index=&quot;2&quot;&gt;
      Dolor sit amet
    &lt;/TabItem&gt;
  &lt;/Tabs&gt;,
  document.getElementById(&quot;root&quot;)
);
````

***

Renders a tag input field.

* Define a `TagInput` component and use the `useState()` hook to initialize an array from `tags`.
* Use `Array.prototype.map()` on the collected nodes to render the list of tags.
* Define the `addTagData` method, which will be executed when pressing the `Enter` key.
* The `addTagData` method calls `setTagData` to add the new tag using the spread (`...`) operator to prepend the existing tags and add the new tag at the end of the `tagData` array.
* Define the `removeTagData` method, which will be executed on clicking the delete icon in the tag.
* Use `Array.prototype.filter()` in the `removeTagData` method to remove the tag using its `index` to filter it out from the `tagData` array.

```
.tag-input {
  display: flex;
  flex-wrap: wrap;
  min-height: 48px;
  padding: 0 8px;
  border: 1px solid #d6d8da;
  border-radius: 6px;
}
.tag-input input {
  flex: 1;
  border: none;
  height: 46px;
  font-size: 14px;
  padding: 4px 0 0;
}
.tag-input input:focus {
  outline: transparent;
}
.tags {
  display: flex;
  flex-wrap: wrap;
  padding: 0;
  margin: 8px 0 0;
}
.tag {
  width: auto;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  padding: 0 8px;
  font-size: 14px;
  list-style: none;
  border-radius: 6px;
  margin: 0 8px 8px 0;
  background: #0052cc;
}
.tag-title {
  margin-top: 3px;
}
.tag-close-icon {
  display: block;
  width: 16px;
  height: 16px;
  line-height: 16px;
  text-align: center;
  font-size: 14px;
  margin-left: 8px;
  color: #0052cc;
  border-radius: 50%;
  background: #fff;
  cursor: pointer;
}
```

````js

const TagInput = ({ tags }) =&gt; {
  const [tagData, setTagData] = React.useState(tags);
  const removeTagData = (indexToRemove) =&gt; {
    setTagData([...tagData.filter((_, index) =&gt; index !== indexToRemove)]);
  };
  const addTagData = (event) =&gt; {
    if (event.target.value !== &quot;&quot;) {
      setTagData([...tagData, event.target.value]);
      event.target.value = &quot;&quot;;
    }
  };
  return (
    &lt;div className=&quot;tag-input&quot;&gt;
      &lt;ul className=&quot;tags&quot;&gt;
        {tagData.map((tag, index) =&gt; (
          &lt;li key={index} className=&quot;tag&quot;&gt;
            &lt;span className=&quot;tag-title&quot;&gt;{tag}&lt;/span&gt;
            &lt;span
              className=&quot;tag-close-icon&quot;
              onClick={() =&gt; removeTagData(index)}
            &gt;
              x
            &lt;/span&gt;
          &lt;/li&gt;
        ))}
      &lt;/ul&gt;
      &lt;input
        type=&quot;text&quot;
        onKeyUp={(event) =&gt; (event.key === &quot;Enter&quot; ? addTagData(event) : null)}
        placeholder=&quot;Press enter to add a tag&quot;
      /&gt;
    &lt;/div&gt;
  );
};



<hr />

```js

ReactDOM.render(
  &lt;TagInput tags={[&quot;Nodejs&quot;, &quot;MongoDB&quot;]} /&gt;,
  document.getElementById(&quot;root&quot;)
);
````

***

Renders an uncontrolled `<textarea>` element that uses a callback function to pass its value to the parent component.

* Use the `defaultValue` passed down from the parent as the uncontrolled input field's initial value.
* Use the `onChange` event to fire the `onValueChange` callback and send the new value to the parent.

```js

const TextArea = ({
  cols = 20,
  rows = 2,
  defaultValue,
  onValueChange,
  ...rest
}) =&gt; {
  return (
    &lt;textarea
      cols={cols}
      rows={rows}
      defaultValue={defaultValue}
      onChange={({ target: { value } }) =&gt; onValueChange(value)}
      {...rest}
    /&gt;
  );
};
```

***

```js

ReactDOM.render(
  &lt;TextArea
    placeholder=&quot;Insert some text here...&quot;
    onValueChange={(val) =&gt; console.log(val)}
  /&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

Renders a toggle component.

* Use the `useState()` hook to initialize the `isToggleOn` state variable to `defaultToggled`.
* Render an `<input>` and bind its `onClick` event to update the `isToggledOn` state variable, applying the appropriate `className` to the wrapping `<label>`.

```
.toggle input[type="checkbox"] {
  display: none;
}
.toggle.on {
  background-color: green;
}
.toggle.off {
  background-color: red;
}
```

````js

const Toggle = ({ defaultToggled = false }) =&gt; {
  const [isToggleOn, setIsToggleOn] = React.useState(defaultToggled);

return (
&lt;label className={isToggleOn ? &quot;toggle on&quot; : &quot;toggle off&quot;}&gt;
&lt;input
type=&quot;checkbox&quot;
checked={isToggleOn}
onChange={() =&gt; setIsToggleOn(!isToggleOn)}
/&gt;
{isToggleOn ? &quot;ON&quot; : &quot;OFF&quot;}
&lt;/label&gt;
);
};



<hr />

```js

ReactDOM.render(&lt;Toggle /&gt;, document.getElementById(&quot;root&quot;));
````

***

Renders a tooltip component.

* Use the `useState()` hook to create the `show` variable and initialize it to `false`.
* Render a container element that contains the tooltip element and the `children` passed to the component.
* Handle the `onMouseEnter` and `onMouseLeave` methods, by altering the value of the `show` variable, toggling the `className` of the tooltip.

```
.tooltip-container {
  position: relative;
}
.tooltip-box {
  position: absolute;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  padding: 5px;
  border-radius: 5px;
  top: calc(100% + 5px);
  display: none;
}
.tooltip-box.visible {
  display: block;
}
.tooltip-arrow {
  position: absolute;
  top: -10px;
  left: 50%;
  border-width: 5px;
  border-style: solid;
  border-color: transparent transparent rgba(0, 0, 0, 0.7) transparent;
}
```

````js

const Tooltip = ({ children, text, ...rest }) =&gt; {
  const [show, setShow] = React.useState(false);

return (
&lt;div className=&quot;tooltip-container&quot;&gt;
&lt;div className={show ? &quot;tooltip-box visible&quot; : &quot;tooltip-box&quot;}&gt;
{text}
&lt;span className=&quot;tooltip-arrow&quot; /&gt;
&lt;/div&gt;
&lt;div
onMouseEnter={() =&gt; setShow(true)}
onMouseLeave={() =&gt; setShow(false)}
{...rest}
&gt;
{children}
&lt;/div&gt;
&lt;/div&gt;
);
};



<hr />

```js

ReactDOM.render(
  &lt;Tooltip text=&quot;Simple tooltip&quot;&gt;
    &lt;button&gt;Hover me!&lt;/button&gt;
  &lt;/Tooltip&gt;,
  document.getElementById(&quot;root&quot;)
);
````

***

Renders a tree view of a JSON object or array with collapsible content.

* Use the value of the `toggled` prop to determine the initial state of the content (collapsed/expanded).
* Use the `useState()` hook to create the `isToggled` state variable and give it the value of the `toggled` prop initially.
* Render a `<span>` element and bind its `onClick` event to alter the component's `isToggled` state.
* Determine the appearance of the component, based on `isParentToggled`, `isToggled`, `name` and checking for `Array.isArray()` on `data`.
* For each child in `data`, determine if it is an object or array and recursively render a sub-tree or a text element with the appropriate style.

```
.tree-element {
  margin: 0 0 0 4px;
  position: relative;
}
.tree-element.is-child {
  margin-left: 16px;
}
div.tree-element:before {
  content: "";
  position: absolute;
  top: 24px;
  left: 1px;
  height: calc(100% - 48px);
  border-left: 1px solid gray;
}
p.tree-element {
  margin-left: 16px;
}
.toggler {
  position: absolute;
  top: 10px;
  left: 0px;
  width: 0;
  height: 0;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  border-left: 5px solid gray;
  cursor: pointer;
}
.toggler.closed {
  transform: rotate(90deg);
}
.collapsed {
  display: none;
}
```

````js

const TreeView = ({
  data,
  toggled = true,
  name = null,
  isLast = true,
  isChildElement = false,
  isParentToggled = true,
}) =&gt; {
  const [isToggled, setIsToggled] = React.useState(toggled);
  const isDataArray = Array.isArray(data);

return (
&lt;div
className={`tree-element ${isParentToggled &amp;&amp; &quot;collapsed&quot;} ${ isChildElement &amp;&amp; &quot;is-child&quot; }`}
&gt;
&lt;span
className={isToggled ? &quot;toggler&quot; : &quot;toggler closed&quot;}
onClick={() =&gt; setIsToggled(!isToggled)}
/&gt;
{name ? &lt;strong&gt;&amp;nbsp;&amp;nbsp;{name}: &lt;/strong&gt; : &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}
{isDataArray ? &quot;[&quot; : &quot;{&quot;}
{!isToggled &amp;&amp; &quot;...&quot;}
{Object.keys(data).map((v, i, a) =&gt;
typeof data[v] === &quot;object&quot; ? (
&lt;TreeView
key={`${name}-${v}-${i}`}
data={data[v]}
isLast={i === a.length - 1}
name={isDataArray ? null : v}
isChildElement
isParentToggled={isParentToggled &amp;&amp; isToggled}
/&gt;
) : (
&lt;p
key={`${name}-${v}-${i}`}
className={isToggled ? &quot;tree-element&quot; : &quot;tree-element collapsed&quot;}
&gt;
{isDataArray ? &quot;&quot; : &lt;strong&gt;{v}: &lt;/strong&gt;}
{data[v]}
{i === a.length - 1 ? &quot;&quot; : &quot;,&quot;}
&lt;/p&gt;
)
)}
{isDataArray ? &quot;]&quot; : &quot;}&quot;}
{!isLast ? &quot;,&quot; : &quot;&quot;}
&lt;/div&gt;
);
};



<hr />

```js

const data = {
  lorem: {
    ipsum: &quot;dolor sit&quot;,
    amet: {
      consectetur: &quot;adipiscing&quot;,
      elit: [
        &quot;duis&quot;,
        &quot;vitae&quot;,
        {
          semper: &quot;orci&quot;,
        },
        {
          est: &quot;sed ornare&quot;,
        },
        &quot;etiam&quot;,
        [&quot;laoreet&quot;, &quot;tincidunt&quot;],
        [&quot;vestibulum&quot;, &quot;ante&quot;],
      ],
    },
    ipsum: &quot;primis&quot;,
  },
};
ReactDOM.render(
  &lt;TreeView data={data} name=&quot;data&quot; /&gt;,
  document.getElementById(&quot;root&quot;)
);
````

***

Renders an uncontrolled `<input>` element that uses a callback function to inform its parent about value updates.

* Use the `defaultValue` passed down from the parent as the uncontrolled input field's initial value.
* Use the `onChange` event to fire the `onValueChange` callback and send the new value to the parent.

```js

const UncontrolledInput = ({ defaultValue, onValueChange, ...rest }) =&gt; {
  return (
    &lt;input
      defaultValue={defaultValue}
      onChange={({ target: { value } }) =&gt; onValueChange(value)}
      {...rest}
    /&gt;
  );
};
```

***

```js

ReactDOM.render(
  &lt;UncontrolledInput
    type=&quot;text&quot;
    placeholder=&quot;Insert some text here...&quot;
    onValueChange={console.log}
  /&gt;,
  document.getElementById(&quot;root&quot;)
);
```

***

Handles asynchronous calls.

* Create a custom hook that takes a handler function, `fn`.
* Define a reducer function and an initial state for the custom hook's state.
* Use the `useReducer()` hook to initialize the `state` variable and the `dispatch` function.
* Define an asynchronous `run` function that will run the provided callback, `fn`, while using `dispatch` to update `state` as necessary.
* Return an object containing the properties of `state` (`value`, `error` and `loading`) and the `run` function.

```js

const useAsync = (fn) =&gt; {
  const initialState = { loading: false, error: null, value: null };
  const stateReducer = (_, action) =&gt; {
    switch (action.type) {
      case &quot;start&quot;:
        return { loading: true, error: null, value: null };
      case &quot;finish&quot;:
        return { loading: false, error: null, value: action.value };
      case &quot;error&quot;:
        return { loading: false, error: action.error, value: null };
    }
  };

const [state, dispatch] = React.useReducer(stateReducer, initialState);

const run = async (args = null) =&gt; {
try {
dispatch({ type: &quot;start&quot; });
const value = await fn(args);
dispatch({ type: &quot;finish&quot;, value });
} catch (error) {
dispatch({ type: &quot;error&quot;, error });
}
};

return { ...state, run };
};
```

***

```js

const RandomImage = (props) =&gt; {
  const imgFetch = useAsync((url) =&gt;
    fetch(url).then((response) =&gt; response.json())
  );

return (
&lt;div&gt;
&lt;button
onClick={() =&gt; imgFetch.run(&quot;https://dog.ceo/api/breeds/image/random&quot;)}
disabled={imgFetch.isLoading}
&gt;
Load image
&lt;/button&gt;
&lt;br /&gt;
{imgFetch.loading &amp;&amp; &lt;div&gt;Loading...&lt;/div&gt;}
{imgFetch.error &amp;&amp; &lt;div&gt;Error {imgFetch.error}&lt;/div&gt;}
{imgFetch.value &amp;&amp; (
&lt;img
src={imgFetch.value.message}
alt=&quot;avatar&quot;
width={400}
height=&quot;auto&quot;
/&gt;
)}
&lt;/div&gt;
);
};

ReactDOM.render(&lt;RandomImage /&gt;, document.getElementById(&quot;root&quot;));
```

***

Handles the event of clicking inside the wrapped component.

* Create a custom hook that takes a `ref` and a `callback` to handle the `'click'` event.
* Use the `useEffect()` hook to append and clean up the `click` event.
* Use the `useRef()` hook to create a `ref` for your click component and pass it to the `useClickInside` hook.

```js

const useClickInside = (ref, callback) =&gt; {
  const handleClick = (e) =&gt; {
    if (ref.current &amp;&amp; ref.current.contains(e.target)) {
      callback();
    }
  };
  React.useEffect(() =&gt; {
    document.addEventListener(&quot;click&quot;, handleClick);
    return () =&gt; {
      document.removeEventListener(&quot;click&quot;, handleClick);
    };
  });
};
```

***

```js

const ClickBox = ({ onClickInside }) =&gt; {
  const clickRef = React.useRef();
  useClickInside(clickRef, onClickInside);
  return (
    &lt;div
      className=&quot;click-box&quot;
      ref={clickRef}
      style={{
        border: &quot;2px dashed orangered&quot;,
        height: 200,
        width: 400,
        display: &quot;flex&quot;,
        justifyContent: &quot;center&quot;,
        alignItems: &quot;center&quot;,
      }}
    &gt;
      &lt;p&gt;Click inside this element&lt;/p&gt;
    &lt;/div&gt;
  );
};

ReactDOM.render(
&lt;ClickBox onClickInside={() =&gt; alert(&quot;click inside&quot;)} /&gt;,
document.getElementById(&quot;root&quot;)
);
```

***

Handles the event of clicking outside of the wrapped component.

* Create a custom hook that takes a `ref` and a `callback` to handle the `click` event.
* Use the `useEffect()` hook to append and clean up the `click` event.
* Use the `useRef()` hook to create a `ref` for your click component and pass it to the `useClickOutside` hook.

```js

const useClickOutside = (ref, callback) =&gt; {
  const handleClick = (e) =&gt; {
    if (ref.current &amp;&amp; !ref.current.contains(e.target)) {
      callback();
    }
  };
  React.useEffect(() =&gt; {
    document.addEventListener(&quot;click&quot;, handleClick);
    return () =&gt; {
      document.removeEventListener(&quot;click&quot;, handleClick);
    };
  });
};
```

***

```js

const ClickBox = ({ onClickOutside }) =&gt; {
  const clickRef = React.useRef();
  useClickOutside(clickRef, onClickOutside);
  return (
    &lt;div
      className=&quot;click-box&quot;
      ref={clickRef}
      style={{
        border: &quot;2px dashed orangered&quot;,
        height: 200,
        width: 400,
        display: &quot;flex&quot;,
        justifyContent: &quot;center&quot;,
        alignItems: &quot;center&quot;,
      }}
    &gt;
      &lt;p&gt;Click out of this element&lt;/p&gt;
    &lt;/div&gt;
  );
};

ReactDOM.render(
&lt;ClickBox onClickOutside={() =&gt; alert(&quot;click outside&quot;)} /&gt;,
document.getElementById(&quot;root&quot;)
);
```

***

Executes a callback immediately after a component is mounted.

* Use `useEffect()` with an empty array as the second argument to execute the provided callback only once when the component is mounted.
* Behaves like the `componentDidMount()` lifecycle method of class components.

```js

const useComponentDidMount = (onMountHandler) =&gt; {
  React.useEffect(() =&gt; {
    onMountHandler();
  }, []);
};
```

***

```js

const Mounter = () =&gt; {
  useComponentDidMount(() =&gt; console.log(&quot;Component did mount&quot;));

return &lt;div&gt;Check the console!&lt;/div&gt;;
};

ReactDOM.render(&lt;Mounter /&gt;, document.getElementById(&quot;root&quot;));
```

***

Executes a callback immediately before a component is unmounted and destroyed.

* Use `useEffect()` with an empty array as the second argument and return the provided callback to be executed only once before cleanup.
* Behaves like the `componentWillUnmount()` lifecycle method of class components.

```js

const useComponentWillUnmount = (onUnmountHandler) =&gt; {
  React.useEffect(
    () =&gt; () =&gt; {
      onUnmountHandler();
    },
    []
  );
};
```

***

```js

const Unmounter = () =&gt; {
  useComponentWillUnmount(() =&gt; console.log(&quot;Component will unmount&quot;));

return &lt;div&gt;Check the console!&lt;/div&gt;;
};

ReactDOM.render(&lt;Unmounter /&gt;, document.getElementById(&quot;root&quot;));
```

***

Copies the given text to the clipboard.

* Use the copyToClipboard snippet to copy the text to clipboard.
* Use the `useState()` hook to initialize the `copied` variable.
* Use the `useCallback()` hook to create a callback for the `copyToClipboard` method.
* Use the `useEffect()` hook to reset the `copied` state variable if the `text` changes.
* Return the `copied` state variable and the `copy` callback.

```js

const useCopyToClipboard = (text) =&gt; {
  const copyToClipboard = (str) =&gt; {
    const el = document.createElement(&quot;textarea&quot;);
    el.value = str;
    el.setAttribute(&quot;readonly&quot;, &quot;&quot;);
    el.style.position = &quot;absolute&quot;;
    el.style.left = &quot;-9999px&quot;;
    document.body.appendChild(el);
    const selected =
      document.getSelection().rangeCount &gt; 0
        ? document.getSelection().getRangeAt(0)
        : false;
    el.select();
    const success = document.execCommand(&quot;copy&quot;);
    document.body.removeChild(el);
    if (selected) {
      document.getSelection().removeAllRanges();
      document.getSelection().addRange(selected);
    }
    return success;
  };

const [copied, setCopied] = React.useState(false);

const copy = React.useCallback(() =&gt; {
if (!copied) setCopied(copyToClipboard(text));
}, [text]);
React.useEffect(() =&gt; () =&gt; setCopied(false), [text]);

return [copied, copy];
};
```

***

```js

const TextCopy = (props) =&gt; {
  const [copied, copy] = useCopyToClipboard(&quot;Lorem ipsum&quot;);
  return (
    &lt;div&gt;
      &lt;button onClick={copy}&gt;Click to copy&lt;/button&gt;
      &lt;span&gt;{copied &amp;&amp; &quot;Copied!&quot;}&lt;/span&gt;
    &lt;/div&gt;
  );
};

ReactDOM.render(&lt;TextCopy /&gt;, document.getElementById(&quot;root&quot;));
```

***

Debounces the given value.

* Create a custom hook that takes a `value` and a `delay`.
* Use the `useState()` hook to store the debounced value.
* Use the `useEffect()` hook to update the debounced value every time `value` is updated.
* Use `setTimeout()` to create a timeout that delays invoking the setter of the previous state variable by `delay` ms.
* Use `clearTimeout()` to clean up when dismounting the component.
* This is particularly useful when dealing with user input.

```js

const useDebounce = (value, delay) =&gt; {
  const [debouncedValue, setDebouncedValue] = React.useState(value);

React.useEffect(() =&gt; {
const handler = setTimeout(() =&gt; {
setDebouncedValue(value);
}, delay);

    return () =&gt; {
      clearTimeout(handler);
    };

}, [value]);

return debouncedValue;
};
```

***

```js

const Counter = () =&gt; {
  const [value, setValue] = React.useState(0);
  const lastValue = useDebounce(value, 500);

return (
&lt;div&gt;
&lt;p&gt;
Current: {value} - Debounced: {lastValue}
&lt;/p&gt;
&lt;button onClick={() =&gt; setValue(value + 1)}&gt;Increment&lt;/button&gt;
&lt;/div&gt;
);
};

ReactDOM.render(&lt;Counter /&gt;, document.getElementById(&quot;root&quot;));
```

***

Implements `fetch` in a declarative manner.

* Create a custom hook that takes a `url` and `options`.
* Use the `useState()` hook to initialize the `response` and `error` state variables.
* Use the `useEffect()` hook to asynchronously call `fetch()` and update the state variables accordingly.
* Return an object containing the `response` and `error` state variables.

```js

const useFetch = (url, options) =&gt; {
  const [response, setResponse] = React.useState(null);
  const [error, setError] = React.useState(null);

React.useEffect(() =&gt; {
const fetchData = async () =&gt; {
try {
const res = await fetch(url, options);
const json = await res.json();
setResponse(json);
} catch (error) {
setError(error);
}
};
fetchData();
}, []);

return { response, error };
};
```

***

```js

const ImageFetch = (props) =&gt; {
  const res = useFetch(&quot;https://dog.ceo/api/breeds/image/random&quot;, {});
  if (!res.response) {
    return &lt;div&gt;Loading...&lt;/div&gt;;
  }
  const imageUrl = res.response.message;
  return (
    &lt;div&gt;
      &lt;img src={imageUrl} alt=&quot;avatar&quot; width={400} height=&quot;auto&quot; /&gt;
    &lt;/div&gt;
  );
};

ReactDOM.render(&lt;ImageFetch /&gt;, document.getElementById(&quot;root&quot;));
```

***

Implements `setInterval` in a declarative manner.

* Create a custom hook that takes a `callback` and a `delay`.
* Use the `useRef()` hook to create a `ref` for the callback function.
* Use a `useEffect()` hook to remember the latest `callback` whenever it changes.
* Use a `useEffect()` hook dependent on `delay` to set up the interval and clean up.

```js

const useInterval = (callback, delay) =&gt; {
  const savedCallback = React.useRef();

React.useEffect(() =&gt; {
savedCallback.current = callback;
}, [callback]);

React.useEffect(() =&gt; {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () =&gt; clearInterval(id);
}
}, [delay]);
};
```

***

```js

const Timer = (props) =&gt; {
  const [seconds, setSeconds] = React.useState(0);
  useInterval(() =&gt; {
    setSeconds(seconds + 1);
  }, 1000);

return &lt;p&gt;{seconds}&lt;/p&gt;;
};

ReactDOM.render(&lt;Timer /&gt;, document.getElementById(&quot;root&quot;));
```

***

Checks if the current environment matches a given media query and returns the appropriate value.

* Check if `window` and `window.matchMedia` exist, return `whenFalse` if not (e.g. SSR environment or unsupported browser).
* Use `window.matchMedia()` to match the given `query`, cast its `matches` property to a boolean and store in a state variable, `match`, using the `useState()` hook.
* Use the `useEffect()` hook to add a listener for changes and to clean up the listeners after the hook is destroyed.
* Return either `whenTrue` or `whenFalse` based on the value of `match`.

```js

const useMediaQuery = (query, whenTrue, whenFalse) =&gt; {
  if (typeof window === &quot;undefined&quot; || typeof window.matchMedia === &quot;undefined&quot;)
    return whenFalse;

const mediaQuery = window.matchMedia(query);
const [match, setMatch] = React.useState(!!mediaQuery.matches);

React.useEffect(() =&gt; {
const handler = () =&gt; setMatch(!!mediaQuery.matches);
mediaQuery.addListener(handler);
return () =&gt; mediaQuery.removeListener(handler);
}, []);

return match ? whenTrue : whenFalse;
};
```

***

```js

const ResponsiveText = () =&gt; {
  const text = useMediaQuery(
    &quot;(max-width: 400px)&quot;,
    &quot;Less than 400px wide&quot;,
    &quot;More than 400px wide&quot;
  );

return &lt;span&gt;{text}&lt;/span&gt;;
};

ReactDOM.render(&lt;ResponsiveText /&gt;, document.getElementById(&quot;root&quot;));
```

***

Checks if the client is online or offline.

* Create a function, `getOnLineStatus`, that uses the `NavigatorOnLine` web API to get the online status of the client.
* Use the `useState()` hook to create an appropriate state variable, `status`, and setter.
* Use the `useEffect()` hook to add listeners for appropriate events, updating state, and cleanup those listeners when unmounting.
* Finally return the `status` state variable.

```js

const getOnLineStatus = () =&gt;
  typeof navigator !== &quot;undefined&quot; &amp;&amp; typeof navigator.onLine === &quot;boolean&quot;
    ? navigator.onLine
    : true;

const useNavigatorOnLine = () =&gt; {
const [status, setStatus] = React.useState(getOnLineStatus());

const setOnline = () =&gt; setStatus(true);
const setOffline = () =&gt; setStatus(false);

React.useEffect(() =&gt; {
window.addEventListener(&quot;online&quot;, setOnline);
window.addEventListener(&quot;offline&quot;, setOffline);

    return () =&gt; {
      window.removeEventListener(&quot;online&quot;, setOnline);
      window.removeEventListener(&quot;offline&quot;, setOffline);
    };

}, []);

return status;
};
```

***

```js

const StatusIndicator = () =&gt; {
  const isOnline = useNavigatorOnLine();

return &lt;span&gt;You are {isOnline ? &quot;online&quot; : &quot;offline&quot;}.&lt;/span&gt;;
};

ReactDOM.render(&lt;StatusIndicator /&gt;, document.getElementById(&quot;root&quot;));
```

***

Returns a stateful value, persisted in `localStorage`, and a function to update it.

* Use the `useState()` hook to initialize the `value` to `defaultValue`.
* Use the `useRef()` hook to create a ref that will hold the `name` of the value in `localStorage`.
* Use 3 instances of the `useEffect()` hook for initialization, `value` change and `name` change respectively.
* When the component is first mounted, use `Storage.getItem()` to update `value` if there's a stored value or `Storage.setItem()` to persist the current value.
* When `value` is updated, use `Storage.setItem()` to store the new value.
* When `name` is updated, use `Storage.setItem()` to create the new key, update the `nameRef` and use `Storage.removeItem()` to remove the previous key from `localStorage`.
* **NOTE:** The hook is meant for use with primitive values (i.e. not objects) and doesn't account for changes to `localStorage` due to other code. Both of these issues can be easily handled (e.g. JSON serialization and handling the `'storage'` event).

```js

const usePersistedState = (name, defaultValue) =&gt; {
  const [value, setValue] = React.useState(defaultValue);
  const nameRef = React.useRef(name);

React.useEffect(() =&gt; {
try {
const storedValue = localStorage.getItem(name);
if (storedValue !== null) setValue(storedValue);
else localStorage.setItem(name, defaultValue);
} catch {
setValue(defaultValue);
}
}, []);

React.useEffect(() =&gt; {
try {
localStorage.setItem(nameRef.current, value);
} catch {}
}, [value]);

React.useEffect(() =&gt; {
const lastName = nameRef.current;
if (name !== lastName) {
try {
localStorage.setItem(name, value);
nameRef.current = name;
localStorage.removeItem(lastName);
} catch {}
}
}, [name]);

return [value, setValue];
};
```

***

```js

const MyComponent = ({ name }) =&gt; {
  const [val, setVal] = usePersistedState(name, 10);
  return (
    &lt;input
      value={val}
      onChange={(e) =&gt; {
        setVal(e.target.value);
      }}
    /&gt;
  );
};

const MyApp = () =&gt; {
const [name, setName] = React.useState(&quot;my-value&quot;);
return (
&lt;&gt;
&lt;MyComponent name={name} /&gt;
&lt;input
value={name}
onChange={(e) =&gt; {
setName(e.target.value);
}}
/&gt;
&lt;/&gt;
);
};

ReactDOM.render(&lt;MyApp /&gt;, document.getElementById(&quot;root&quot;));
```

***

Stores the previous state or props.

* Create a custom hook that takes a `value`.
* Use the `useRef()` hook to create a `ref` for the `value`.
* Use the `useEffect()` hook to remember the latest `value`.

```js

const usePrevious = (value) =&gt; {
  const ref = React.useRef();
  React.useEffect(() =&gt; {
    ref.current = value;
  });
  return ref.current;
};
```

***

```js

const Counter = () =&gt; {
  const [value, setValue] = React.useState(0);
  const lastValue = usePrevious(value);

return (
&lt;div&gt;
&lt;p&gt;
Current: {value} - Previous: {lastValue}
&lt;/p&gt;
&lt;button onClick={() =&gt; setValue(value + 1)}&gt;Increment&lt;/button&gt;
&lt;/div&gt;
);
};

ReactDOM.render(&lt;Counter /&gt;, document.getElementById(&quot;root&quot;));
```

***

Checks if the code is running on the browser or the server.

* Create a custom hook that returns an appropriate object.
* Use `typeof window`, `window.document` and `Document.createElement()` to check if the code is running on the browser.
* Use the `useState()` hook to define the `inBrowser` state variable.
* Use the `useEffect()` hook to update the `inBrowser` state variable and clean up at the end.
* Use the `useMemo()` hook to memoize the return values of the custom hook.

```js

const isDOMavailable = !!(
  typeof window !== &quot;undefined&quot; &amp;&amp;
  window.document &amp;&amp;
  window.document.createElement
);

const useSSR = () =&gt; {
const [inBrowser, setInBrowser] = React.useState(isDOMavailable);

React.useEffect(() =&gt; {
setInBrowser(isDOMavailable);
return () =&gt; {
setInBrowser(false);
};
}, []);

const useSSRObject = React.useMemo(
() =&gt; ({
isBrowser: inBrowser,
isServer: !inBrowser,
canUseWorkers: typeof Worker !== &quot;undefined&quot;,
canUseEventListeners: inBrowser &amp;&amp; !!window.addEventListener,
canUseViewport: inBrowser &amp;&amp; !!window.screen,
}),
[inBrowser]
);

return React.useMemo(
() =&gt; Object.assign(Object.values(useSSRObject), useSSRObject),
[inBrowser]
);
};
```

***

```js

const SSRChecker = (props) =&gt; {
  let { isBrowser, isServer } = useSSR();

return &lt;p&gt;{isBrowser ? &quot;Running on browser&quot; : &quot;Running on server&quot;}&lt;/p&gt;;
};

ReactDOM.render(&lt;SSRChecker /&gt;, document.getElementById(&quot;root&quot;));
```

***

Implements `setTimeout` in a declarative manner.

* Create a custom hook that takes a `callback` and a `delay`.
* Use the `useRef()` hook to create a `ref` for the callback function.
* Use the `useEffect()` hook to remember the latest callback.
* Use the `useEffect()` hook to set up the timeout and clean up.

```js

const useTimeout = (callback, delay) =&gt; {
  const savedCallback = React.useRef();

React.useEffect(() =&gt; {
savedCallback.current = callback;
}, [callback]);

React.useEffect(() =&gt; {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setTimeout(tick, delay);
return () =&gt; clearTimeout(id);
}
}, [delay]);
};
```

***

```js

const OneSecondTimer = (props) =&gt; {
  const [seconds, setSeconds] = React.useState(0);
  useTimeout(() =&gt; {
    setSeconds(seconds + 1);
  }, 1000);

return &lt;p&gt;{seconds}&lt;/p&gt;;
};

ReactDOM.render(&lt;OneSecondTimer /&gt;, document.getElementById(&quot;root&quot;));
```

***

Provides a boolean state variable that can be toggled between its two states.

* Use the `useState()` hook to create the `value` state variable and its setter.
* Create a function that toggles the value of the `value` state variable and memoize it, using the `useCallback()` hook.
* Return the `value` state variable and the memoized toggler function.

```js

const useToggler = (initialState) =&gt; {
  const [value, setValue] = React.useState(initialState);

const toggleValue = React.useCallback(() =&gt; setValue((prev) =&gt; !prev), []);

return [value, toggleValue];
};
```

***

```js

const Switch = () =&gt; {
  const [val, toggleVal] = useToggler(false);
  return &lt;button onClick={toggleVal}&gt;{val ? &quot;ON&quot; : &quot;OFF&quot;}&lt;/button&gt;;
};
ReactDOM.render(&lt;Switch /&gt;, document.getElementById(&quot;root&quot;));
```

***

Handles the `beforeunload` window event.

* Use the `useRef()` hook to create a ref for the callback function, `fn`.
* Use the `useEffect()` hook and `EventTarget.addEventListener()` to handle the `'beforeunload'` (when the user is about to close the window).
* Use `EventTarget.removeEventListener()` to perform cleanup after the component is unmounted.

```js

const useUnload = (fn) =&gt; {
  const cb = React.useRef(fn);

React.useEffect(() =&gt; {
const onUnload = cb.current;
window.addEventListener(&quot;beforeunload&quot;, onUnload);
return () =&gt; {
window.removeEventListener(&quot;beforeunload&quot;, onUnload);
};
}, [cb]);
};
```

***

```js

const App = () =&gt; {
  useUnload((e) =&gt; {
    e.preventDefault();
    const exit = confirm(&quot;Are you sure you want to leave?&quot;);
    if (exit) window.close();
  });
  return &lt;div&gt;Try closing the window.&lt;/div&gt;;
};
ReactDOM.render(&lt;App /&gt;, document.getElementById(&quot;root&quot;));
```

***
