# 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;));
```

***


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bryan-guner.gitbook.io/my-docs/untitled-1/content/intro-to-react-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
