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.

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" />
More About React

React.js is a JavaScript library that can be used to build user interfaces. With React, users can create reusable components, and these components display data as it changes over time. React Native also exists to help you create native mobile apps using React (the more common approach for users). In other words, React is a JavaScript tool that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces. It provides the means to declaratively define and divide a UI into UI components (a.k.a., React components) using HTML-like nodes called React nodes. React nodes eventually get transformed into a format for UI rendering (e.g., HTML/DOM, canvas, svg, etc.).

I could ramble on trying to express in words what React is, but I think it best to just show you. What follows is a whirlwind tour of React and React components from thirty thousand feet. Don't try and figure out all the details yet as I describe React in this section. The entire book is meant to unwrap the details showcased in the following overview. Still asking, what is react? Just follow along grabbing a hold of the big concepts for now.

Using React to create UI components similar to a <select>

Below is an HTML <select> element that encapsulates child HTML <option> elements. Hopefully the creation and functionality of an HTML <select> is already familiar.

When a browser parses the above tree of elements it will produce a UI containing a textual list of items that can be selected. Click on the "Result" tab in the above JSFiddle, to see what the browser produces.

The browser, the DOM, and the shadow DOM are working together behind the scenes to turn the <select> HTML into a UI component. Note that the <select> component allows the user to make a selection thus storing the state of that selection (i.e., click on "Volvo", and you have selected it instead of "Mercedes").

Using React you can create a custom <select> by using React nodes to make a React component that eventually will result in HTML elements in an HTML DOM.

Let's create our own <select>-like UI component using React.

Defining a React component

Below I am creating a React component by invoking the React.createClass function in order to create a MySelect React component.

As you can see, the MySelect component is made up of some styles and an empty React <div> node element.

//const MySelect = React.createClass({ //define MySelect componentrender: function(){const mySelectStyle = {border: '1px solid #999',display: 'inline-block',padding: '5px'};// using {} to reference a JS variable inside of JSXreturn <div style={mySelectStyle}></div>; //react div element, via JSX}});

That <div> is an HTML-like tag, yes in JavaScript, called JSX. JSX is an optional custom JavaScript syntax used by React to express React nodes that can map to real HTML elements, custom elements, and text nodes. React nodes, defined using JSX should not be considered a one to one match to HTML elements. There are differences and some gotchas.

JSX syntax must be transformed from JSX to real JavaScript in order to be parsed by ES5 JS engines. The above code, if not transformed would of course cause a JavaScript error.

The official tool used to transform JSX to actual JavaScript code is called Babel.

After Babel (or something similar) transforms the JSX <div> in the above code into real JavaScript, it will look like this:

return React.createElement('div', { style: mySelectStyle });

instead of this:

return <div style={mySelectStyle}>
</div>;

For now, just keep in mind that when you write HTML-like tags in React code, eventually it must be transformed into real JavaScript, along with any ES6 syntax.

The <MySelect> component at this point consist of an empty React <div> node element. That's a rather trivial component, so let's change it.

I'm going to define another component called <MyOption> and then use the <MyOption> component within the <MySelect> component (a.k.a., composition).

Examine the updated JavaScript code below which defines both the <MySelect> and <MyOption> React components.

//const MySelect = React.createClass({render: function(){const mySelectStyle = {border: '1px solid #999',display: 'inline-block',padding: '5px'};return ( //react div element, via JSX, containing <MyOption> component<div style={mySelectStyle}><MyOption value="Volvo"></MyOption><MyOption value="Saab"></MyOption><MyOption value="Mercedes"></MyOption><MyOption value="Audi"></MyOption></div>);}});const MyOption = React.createClass({  //define MyOption componentrender: function(){return <div>{this.props.value}</div>; //react div element, via JSX}});

You should note how the <MyOption> component is used inside of the <MySelect> component and that both are created using JSX.

Passing Component Options Using React attributes/props

Notice that the <MyOption> component is made up of one <div> containing the expression {this.props.value}. The {} brackets indicate to JSX that a JavaScript expression is being used. In other words, inside of {} you can write JavaScript.

The {} brackets are used to gain access (i.e., this.props.value) to the properties or attributes passed by the <MyOption> component. In other words, when the <MyOption> component is rendered the value option, passed using an HTML-like attribute (i.e., value="Volvo"), will be placed into the <div>. These HTML looking attributes are considered React attributes/props. React uses them to pass stateless/immutable options into components. In this case we are simply passing the value prop to the <MyOption> component. Not unlike how an argument is passed to a JavaScript function. And in fact that is exactly what is going on behind the JSX.

Rendering a component to the Virtual DOM, then HTML DOM

At this point our JavaScript only defines two React Components. We have yet to actually render these components to the Virtual DOM and thus to the HTML DOM.

Before we do that I'd like to mention that up to this point all we have done is define two React components using JavaScript. In theory, the JavaScript we have so far is just the definition of a UI component. It doesn't strictly have to go into a DOM, or even a Virtual DOM. This same definition, in theory, could also be used to render this component to a native mobile platform or an HTML canvas. But we're not going to do that, even though we could. Just be aware that React is a pattern for organizing a UI that can transcend the DOM, front-end applications, and even the web platform.

Let's now render the <MySelect> component to the virtual DOM which in turn will render it to the actual DOM inside of an HTML page.

In the JavaScript below notice I added a call to the ReactDOM.render() function on the last line. Here I am passing the ReactDOM.render() function the component we want to render (i.e., <MySelect>) and a reference to the HTML element already in the HTML DOM (i.e., `

`) where I want to render my React `` component.

Click on the "Result" tab and you will see our custom React <MySelect> component rendered to the HTML DOM.

Note that all I did was tell React where to start rendering components and which component to start with. React will then render any children components (i.e., <MyOption>) contained within the starting component (i.e., <MySelect>).

Hold up, you might be thinking. We haven't actually created a <select> at all. All we have done is create a static/stateless list of text strings. We'll fix that next.

Before I move on I want to point out that no implicit DOM interactions were written to get the <MySelect> component into the real DOM. In other words, no jQuery code was invoked during the creation of this component. The dealings with the actual DOM have all been abstracted by the React virtual DOM. In fact, when using React what you are doing is describing a virtual DOM that React takes and uses to create a real DOM for you.

Using React state

In order for our <MySelect> component to mimic a native <select> element we are going to have to add state. After all what good is a custom <select> element if it can't keep the state of the selection.

State typically gets involved when a component contains snapshots of information. In regards to our custom <MyOption> component, its state is the currently selected text or the fact that no text is selected at all. Note that state will typically involve user events (i.e., mouse, keyboard, clipboard, etc.) or network events (i.e., AJAX) and its value is used to determine when the UI needs to be re-rendered (i.e., when value changes re-render).

State is typically found on the top most component which makes up a UI component. Using the React getInitialState() function we can set the default state of our component to false (i.e., nothing selected) by returning a state object when getInitialState is invoked (i.e., return {selected: false};). The getInitialState lifecycle method gets invoked once before the component is mounted. The return value will be used as the initial value of this.state.

I've updated the code below accordingly to add state to the component. As I am making updates to the code, make sure you read the JavaScript comments which call attention to the changes in the code.

//const MySelect = React.createClass({getInitialState: function(){ //add selected, default statereturn {selected: false}; //this.state.selected = false;},render: function(){const mySelectStyle = {border: '1px solid #999',display: 'inline-block',padding: '5px'};return (<div style={mySelectStyle}><MyOption value="Volvo"></MyOption><MyOption value="Saab"></MyOption><MyOption value="Mercedes"></MyOption><MyOption value="Audi"></MyOption></div>);}});const MyOption = React.createClass({render: function(){return <div>{this.props.value}</div>;}});

ReactDOM.render(<MySelect />, document.getElementById('app'));

With the default state set, next we'll add a callback function called select that gets called when a user clicks on an option. Inside of this function we get the text of the option that was selected (via the event parameter) and use that to determine how to setState on the current component. Notice that I am using event details passed to the select callback. This pattern should look familiar if you've had any experience with jQuery.

//const MySelect = React.createClass({getInitialState: function(){return {selected: false};},select:function(event){// added select functionif(event.target.textContent === this.state.selected){//remove selectionthis.setState({selected: false}); //update state}else{//add selectionthis.setState({selected: event.target.textContent}); //update state}},render: function(){const mySelectStyle = {border: '1px solid #999',display: 'inline-block',padding: '5px'};return (<div style={mySelectStyle}><MyOption value="Volvo"></MyOption><MyOption value="Saab"></MyOption><MyOption value="Mercedes"></MyOption><MyOption value="Audi"></MyOption></div>);}});const MyOption = React.createClass({render: function(){return <div>{this.props.value}</div>;}});

ReactDOM.render(<MySelect />, document.getElementById('app'));

In order for our <MyOption> components to gain access to the select function we'll have to pass a reference to it, via props, from the <MySelect> component to the <MyOption> component. To do this we add select={this.select} to the <MyOption> components.

With that in place we can add onClick={this.props.select} to the <MyOption> components. Hopefully it's obvious that all we have done is wired up a click event that will call the select function. React takes care of wiring up the real click handler in the real DOM for you.

//const MySelect = React.createClass({getInitialState: function(){return {selected: false};},select:function(event){if(event.target.textContent === this.state.selected){this.setState({selected: false});}else{this.setState({selected: event.target.textContent});}},render: function(){const mySelectStyle = {border: '1px solid #999',display: 'inline-block',padding: '5px'};return (//pass reference, using props, to select callback to <MyOption><div style={mySelectStyle}><MyOption select={this.select} value="Volvo"></MyOption><MyOption select={this.select} value="Saab"></MyOption><MyOption select={this.select} value="Mercedes"></MyOption><MyOption select={this.select} value="Audi"></MyOption></div>);}});const MyOption = React.createClass({render: function(){//add event handler that will invoke select callbackreturn <div onClick={this.props.select}>{this.props.value}</div>;}});

ReactDOM.render(<MySelect />, document.getElementById('app'));

By doing all this we can now set the state by clicking on one of the options. In other words, when you click on an option the select function will now run and set the state of the MySelect component. However, the user of the component has no idea this is being done because all we have done is update our code so that state is managed by the component. At this point we have no feedback visually that anything is selected. Let's fix that.

The next thing we will need to do is pass the current state down to the <MyOption> component so that it can respond visually to the state of the component.

Using props, again, we will pass the selected state from the <MySelect> component down to the <MyOption> component by placing the property state={this.state.selected} on all of the <MyOption> components. Now that we know the state (i.e., this.props.state) and the current value (i.e., this.props.value) of the option we can verify if the state matches the value in a given <MyOption> component . If it does, we then know that this option should be selected. We do this by writing a simple if statement which adds a styled selected state (i.e., selectedStyle) to the JSX <div> if the state matches the value of the current option. Otherwise, we return a React element with unSelectedStyle styles.

Make sure you click on the "Result" tab above and use the custom React select component to verify the new functioning.

While our React UI select component is not as pretty or feature complete as you might hope, I think you can see still where all this is going. React is a tool that can help you reason about, construct, and maintain stateless and stateful UI components, in a structure tree (i.e., a tree of components).

Before moving on to the role of the virtual DOM I do want to stress that you don't have to use JSX and Babel. You can always bypass these tools and just write straight JavaScript. Below, I'm showing the final state of the code after the JSX has been transformed by Babel. If you choose not to use JSX, then you'll have to write the following code yourself instead of the code I've written throughout this section.

//const MySelect = React.createClass({displayName: 'MySelect',getInitialState: function getInitialState() {return { selected: false };},select: function select(event) {if (event.target.textContent === this.state.selected) {this.setState({ selected: false });} else {this.setState({ selected: event.target.textContent });}},render: function render() {const mySelectStyle = {border: '1px solid #999',display: 'inline-block',padding: '5px'};return React.createElement('div',{ style: mySelectStyle },
      React.createElement(MyOption, { state: this.state.selected, select: this.select, value: 'Volvo' }),
      React.createElement(MyOption, { state: this.state.selected, select: this.select, value: 'Saab' }),
      React.createElement(MyOption, { state: this.state.selected, select: this.select, value: 'Mercedes' }),
      React.createElement(MyOption, { state: this.state.selected, select: this.select, value: 'Audi' }));}});const MyOption = React.createClass({displayName: 'MyOption',render: function render() {const selectedStyle = { backgroundColor: 'red', color: '#fff', cursor: 'pointer' };const unSelectedStyle = { cursor: 'pointer' };if (this.props.value === this.props.state) {return React.createElement('div',{ style: selectedStyle, onClick: this.props.select },this.props.value
      );} else {return React.createElement('div',{ style: unSelectedStyle, onClick: this.props.select },this.props.value
      );}}});

ReactDOM.render(React.createElement(MySelect, null), document.getElementById('app'));

Understanding the role of the Virtual DOM

I'm going to end this whirlwind tour where most people typically start talking about React. I'll finish off this React overview by talking about the merits of the React virtual DOM.

Hopefully you notice the only interaction with the real DOM we had during the creation of our custom select UI is when we told the ReactDOM.render() function where to render our UI component in the HTML page (i.e., render it to `

`). This might just be the only interaction you ever have with the real DOM when building out a React application from a tree of React components. And herein lies much of the value of React. By using React, you really don't ever have to think about the DOM like you once did when you were writing jQuery code. React replaces jQuery, as a complete DOM abstraction, by removing most, if not all, implicit DOM interactions from your code. Of course, that's not the only benefit, or even the best benefit.

Because the DOM has been completely abstracted by the Virtual DOM this allows for a heavy handed performance pattern of updating the real DOM when state is changed. The Virtual DOM keeps track of UI changes based on state and props. It then compares that to the real DOM, and then makes only the minimal changes required to update the UI. In other words, the real DOM is only ever patched with the minimal changes needed when state or props change.

  • Seeing these performant updates in real time will often clarify any confusion about the performant DOM diffing. Look at the animated image below showcasing the usage (i.e., changing state) of the UI component we created in this chapter.
  • Notice that as the UI component changes state only the minimally needed changes to the real DOM are occurring. We know that React is doing it's job because the only parts of the real DOM that are actually being updated are the parts with a green outline/background. The entire UI component is not being updated on each state change, only the parts that require a change.

Let me be clear, this isn't a revolutionary concept. You could accomplish the same thing with some carefully crafted and performant minded jQuery code. However, by using React you'll rarely, if ever, have to think about it. The Virtual DOM is doing all the performance work for you. In a sense, this is the best type of jQuery/DOM abstraction possible. One where you don't even have to worry about, or code for, the DOM. It all just happens behinds the scene without you ever implicitly having to interact with the DOM itself.

Now, it might be tempting to leave this overview thinking the value of React is contained in the fact that it almost eliminates the need for something like jQuery. And while the Virtual DOM is certainly a relief when compared to implicit jQuery code, the value of React does not rest alone on the Virtual DOM. The Virtual DOM is just the icing on the cake. Simply stated, the value of React rests upon the fact it provides a simple and maintainable pattern for creating a tree of UI components. Imagine how simple programming a UI could be by defining the entire interface of your application using reusable React components alone.

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.


```js
//

    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.> The line-break tag, for example, must always be written as_ `<br />` _in order to be valid JSX that can be transpiled.> A_ `<div>`_, on the other hand, can be written as_ `<div />`_or_`<div>
</div>`_.> 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.```js
//

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

### Ans:

```js
//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
  }
};

See More

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:

Answers
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>
    );
  }
};
    
 </details>   
    

### More Examples:



<a href="https://github.com/bgoonz" class="markup--anchor markup--mixtapeEmbed-anchor" title="https://github.com/bgoonz">
<strong>bgoonz - Overview</strong>
<br />
<em>Web Developer, Electrical Engineer https://bryanguner.medium.com/ https://portfolio42.netlify.app/…</em>github.com</a>
<a href="https://github.com/bgoonz" class="js-mixtapeImage mixtapeImage u-ignoreBlock">
</a>

_More content at_ <a href="http://plainenglish.io/" class="markup--anchor markup--p-anchor">
<em>plainenglish.io</em>
</a>

By <a href="https://medium.com/@bryanguner" class="p-author h-card">Bryan Guner</a> on [May 19, 2021](https://medium.com/p/8021738aa1ad).

<a href="https://medium.com/@bryanguner/introduction-to-react-for-complete-beginners-8021738aa1ad" class="p-canonical">Canonical link</a>

 May 23, 2021.

# Snippets:

<p>Renders an accordion menu with multiple collapsible content elements.</p>
<ul>
<li>Define an <code>AccordionItem</code> component, that renders a <code>&lt;button&gt;</code> which is used to update the component and notify its parent via the <code>handleClick</code> callback.</li>
<li>Use the <code>isCollapsed</code> prop in <code>AccordionItem</code> to determine its appearance and set an appropriate <code>className</code>.</li>
<li>Define an <code>Accordion</code> component that uses the <code>useState()</code> hook to initialize the value of the <code>bindIndex</code> state variable to <code>defaultIndex</code>.</li>
<li>Filter <code>children</code> to remove unnecessary nodes except for <code>AccordionItem</code> by identifying the function's name.</li>
<li>Use <code>Array.prototype.map()</code> on the collected nodes to render the individual collapsible elements.</li>
<li>Define <code>changeItem</code>, which will be executed when clicking an <code>AccordionItem</code>'s <code>&lt;button&gt;</code>.</li>
<li>
<code>changeItem</code> executes the passed callback, <code>onItemClick</code>, and updates <code>bindIndex</code> based on the clicked element.</li>
</ul>
<div class="sourceCode" id="cb1">
<pre class="sourceCode css">
<code class="sourceCode css">
<a class="sourceLine" id="cb1-1" title="1">
<span class="fu">.accordion-item.collapsed</span> {</a>
<a class="sourceLine" id="cb1-2" title="2">  <span class="kw">display</span>: <span class="dv">none</span>
<span class="op">;</span>
</a>
<a class="sourceLine" id="cb1-3" title="3">}</a>
<a class="sourceLine" id="cb1-4" title="4">
</a>
<a class="sourceLine" id="cb1-5" title="5">
<span class="fu">.accordion-item.expanded</span> {</a>
<a class="sourceLine" id="cb1-6" title="6">  <span class="kw">display</span>: <span class="dv">block</span>
<span class="op">;</span>
</a>
<a class="sourceLine" id="cb1-7" title="7">}</a>
<a class="sourceLine" id="cb1-8" title="8">
</a>
<a class="sourceLine" id="cb1-9" title="9">
<span class="fu">.accordion-button</span> {</a>
<a class="sourceLine" id="cb1-10" title="10">  <span class="kw">display</span>: <span class="dv">block</span>
<span class="op">;</span>
</a>
<a class="sourceLine" id="cb1-11" title="11">  <span class="kw">width</span>: <span class="dv">100</span>
<span class="dt">%</span>
<span class="op">;</span>
</a>
<a class="sourceLine" id="cb1-12" title="12">}</a>

</div>

```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().
//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.
//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;);};

//

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.
//const Callto = ({ phone, children }) =&gt; {return &lt;a href={`tel:${phone}`}&gt;{children}&lt;/a&gt;;};

//

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.
//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.
//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.
//const ControlledInput = ({ value, onValueChange, ...rest }) =&gt; {return (&lt;input
      value={value}
      onChange={({ target: { value } }) =&gt; onValueChange(value)}{...rest}/&gt;);};

//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.
//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;);};

//

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.
//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;;};

//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.
//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;);};

//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.
//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.
//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;);};

//

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.
//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;);};

//

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.
//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.
//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;;};

//

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

//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;);};

//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.
//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.
//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;);};

//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".
//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;);};

//

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.
//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.
//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;);};

//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.
//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;);};

//

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.
//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.
//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.
//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.
//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;);};

//

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>.
//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.
//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.
//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.
//const UncontrolledInput = ({ defaultValue, onValueChange, ...rest }) =&gt; {return (&lt;input
      defaultValue={defaultValue}
      onChange={({ target: { value } }) =&gt; onValueChange(value)}{...rest}/&gt;);};

//

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.
//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 };};

//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.
//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);};});};

//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.
//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);};});};

//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.
//const useComponentDidMount = (onMountHandler) =&gt; {
  React.useEffect(() =&gt; {onMountHandler();}, []);};

//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.
//const useComponentWillUnmount = (onUnmountHandler) =&gt; {
  React.useEffect(() =&gt; () =&gt; {onUnmountHandler();},[]);};

//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.
//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];};

//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.
//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;};

//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.
//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 };};

//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.
//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]);};

//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.
//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;};

//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.
//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;};

//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).
//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];};

//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.
//const usePrevious = (value) =&gt; {const ref = React.useRef();
  React.useEffect(() =&gt; {
    ref.current = value;});return ref.current;};

//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.
//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]);};

//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.
//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]);};

//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.
//const useToggler = (initialState) =&gt; {const [value, setValue] = React.useState(initialState);const toggleValue = React.useCallback(() =&gt; setValue((prev) =&gt; !prev), []);return [value, toggleValue];};

//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.
//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]);};

//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;));