Component Glossary 📖
Tags: react
Published: 2019-06-26 06:25:09

---
title: Component Glossary 📖
published: true
description: Explanation of various types of components with words and code.
tags: ['ReactJs']
---

> Originally published on https://smellycode.com/component-glossary/

![](https://smellycode.com/static/d13221366e77db5c8133d7dfbc2a03b5/4efde/component-glossary-cover-img.jpg)

Components are basic building blocks of modern web applications. They help web developers to break complex user interfaces into independent smaller blocks or pieces which can be reused and plugged with other pieces or components as is. In general, a component is

> "a part or element of a larger whole, especially a part of a machine or vehicle." ~ <a href="https://www.google.com/search?rlz=1C5CHFA_enIN836IN837&ei=stAJXdmCIsX1vgSa7YmYDA&q=define%3Acomponent&oq=define%3Acomponent&gs_l=psy-ab.3...126435.129603..129948...3.0..0.165.2102.7j12......0....1..gws-wiz.......0i71j0i67j35i39.a9m9W10kFE8" target="_blank">Google</a>

This article explains various types of components with words and code.

### Function Components

Function Components are JavaScript functions which take inputs known as _props_ and returns a <a href="https://reactjs.org/docs/rendering-elements.html" target="_blank">React Element</a> as output. Here's a simple `Greetings` function component to greet.

```js
function Greetings(props) {
  return <h1>Hello {props.name}</h1>;
}

// With arrow function
// const Greetings = props => <h1>Hello {props.name}</h1>;
```

People often mix up function components with "Functional Components". **Every component is a functional component if it is functioning or working fine**. 😀

React does not <a href="https://javascript.info/constructor-new" target="_blank">instantiate</a> function components. It means they can not be accessed with the <a href="https://reactjs.org/docs/refs-and-the-dom.html" target="_blank">ref attribute</a>. Lack of instantiation also makes the <a href="https://reactjs.org/docs/state-and-lifecycle.html#adding-lifecycle-methods-to-a-class" target="_blank">life-cycle hooks</a> inaccessible to function components.

Function components don't have any state unless they are <a href="https://reactjs.org/docs/hooks-intro.html">hooked</a>.

### <a name="classComponents"></a> Class Components

Components created with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes" target="_blank">ES6 Classes</a> are known as _Class Components_. Class components extend the base class <a href="https://reactjs.org/docs/react-component.html" target="_blank">React.Component</a>. Unlike function components, class components can have state and access the life-cycle methods. Class Components define a `render` method which returns a react element as output. Here's a simple `Clock` component to display time.

```js
class Clock extends React.Component {
  state = { now: new Date() };

  intervalId = null;

  updateTime = () => this.setState({ now: new Date() });

  componentDidMount() {
    this.intervalId = setInterval(() => this.updateTime(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.intervalId);
  }

  render() {
    return <p>{this.state.now.toLocaleTimeString({}, { hour12: true })}</p>;
  }
}
```

Instances of class components can be accessed with the _ref attribute_.

```javascript
class App extends React.Component {
  clockRef = React.createRef();

  componentDidMount() {
    // instance of the clock component
    console.log(this.clockRef.current);
  }

  render() {
    return <Clock ref={this.clockRef} />;
  }
}
```

### Pure Components

Let's discuss a simple `Greetings` <a href="https://reactjs.org/docs/react-component.html" target="_blank">React.Component</a> first.

```js
class Greetings extends React.Component {
  render() {
    console.count('Greetings --> render');
    return <p>Hello {this.props.name}!</p>;
  }
}
```

It greets with a `name` passed as props. An additional <a href="https://developer.mozilla.org/en-US/docs/Web/API/Console/count" target="_blank">console.count</a> statement is added to `render` method to count executions.

The `App` component below takes `name` from a form input control and passes it to the `Greetings` component.

```js
class App extends React.Component {
  state = { name: 'Sheldon', text: '' };

  handleChange = event => {
    this.setState({ text: event.target.value });
  };

  handleSubmit = event => {
    event.preventDefault();
    this.setState({ text: '', name: this.state.text });
  };

  render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <input
            type="text"
            value={this.state.text}
            required
            onChange={this.handleChange}
          />
          <input type="submit" value="Greet" />
        </form>
        <Greetings name={this.state.name} />
      </div>
    );
  }
}
```

When a user interacts with the input control, it updates the state of the `App` component. React invokes the `render` method--with the updated state and props--of the `App` component and _its children_ to <a href="https://reactjs.org/docs/reconciliation.html" target="_blank">create a new React Element tree for diffing</a>. Although, the state and props of the `Greetings` component are not changed, still React calls the `render` method of the `Greetings` component.

In large applications, such **unnecessary executions of `render` methods create performance issues and bog down user interfaces**. The <a href="https://reactjs.org/docs/react-component.html#shouldcomponentupdate">_shouldComponentUpdate_</a> life-cycle method is used to avoid these unnecessary re-renderings of the component. By default, `shouldComponentUpdate` return true, but its implementation can be easily overridden. Let's override `shouldComponentUpdate` for the `Greetings` component.

```js
class Greetings extends React.Component {
  shouldComponentUpdate(nextProps) {
    // Re-render only when the `name` prop changes.
    return this.props.name !== nextProps.name;
  }

  render() {
    console.count('Greetings --> render');
    return <p>Hello {this.props.name}!</p>;
  }
}
```

After the very first render, `Greetings` component is re-rendered only when the `name` prop changes.

To solve the same problem, React introduces a variant of React.Component called <a href="https://reactjs.org/docs/react-api.html#reactpurecomponent" target="_blank">React.PureComponent</a> which implicitly implements `shouldComponentUpdate`. **The implicit implementation compares props and state by reference(shallow comparison)**. Let's write the pure version of `Greetings`.

```js
class PureGreetings extends React.PureComponent {
  render() {
    console.count('Pure Greetings --> render');
    return <span>Hello {this.props.name}!</span>;
  }
}
```

Here's the <a href="https://codepen.io/smellycode/pen/QXgjzq?editors=0010" target="_blank">pen</a> with full code.

### Controlled/Uncontrolled Components

Working with form elements is a tad tedious. It requires a lot of malarky to get data from the form elements. That's because form elements maintain their own state internally. Developers have to throw a few lines to JavaScript to get the job done. Form elements in React are no exception. The way developers deal with a form element determines whether that element is a _Controlled or Uncontrolled_ Element/Component. If the value of a form element is controlled by React then it's called a "Controlled Component" otherwise "Uncontrolled Component".

**Controlled Components don't change their state on user interaction**. State changes happen only when the parent component decides eg. the `SubscriptionForm` component below doesn't honor user inputs (<a href="https://codepen.io/smellycode/pen/LKbEoX?editors=0010" target="_blank">Codepen</a>).

```javascript
class SubscriptionForm extends React.Component {
  handleSubmit = event => {
    event.preventDefault();
  };
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="email" value="smelly@smellycode.com" />
        <input type="submit" value="Subscribe" />
      </form>
    );
  }
}
```

_Why changes are not honored?_ That's because the `value` attribute for the email input is set to `smelly@smellycode.com`. When React runs <a href="https://reactjs.org/docs/reconciliation.html" target="_blank">the diffing algorithm</a> on the render tree. It always gets the email input as `smelly@smellycode.com` so it ends up rendering the same value regardless of inputs entered by the user. Let's fix it by setting up an event listener which will update the state on `change` event(<a href="https://codepen.io/smellycode/pen/wLoKRR?editors=0010" target="_blank">Codepen</a>).

```javascript
class SubscriptionForm extends React.Component {
  state = { email: '' };

  handleSubmit = event => {
    event.preventDefault();
    console.log('Values --> ', this.state);
  };

  handleChange = event => this.setState({ email: event.target.value });

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input
          type="email"
          value={this.state.email}
          onChange={this.handleChange}
        />
        <input type="submit" value="Subscribe" />
      </form>
    );
  }
}
```

Everything that goes into the input form elements is controlled by React here. That's why it is called "Controlled Component".

For "Uncontrolled Component", form data is not handled by React. DOM takes care of them. Here's an uncontrolled version of the `SubscriptionForm`.

```js
class SubscriptionForm extends React.Component {
  inputRef = React.createRef();

  handleSubmit = event => {
    event.preventDefault();
    console.log('Value -->', this.inputRef.current.value);
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="email" ref={this.inputRef} />
        <input type="submit" value="Subscribe" />
      </form>
    );
  }
}
```

For elaborative comparison please refer <a href="https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/" target="_blank">the article</a>.

### Higher Order Components

Suppose there's an application which has a few malformed components--_components whose elements/children are invalid react elements_. Rendering of these components breaks the user interface.

```javascript
// A sample malformed component.
class MalformedComponent extends React.Component {
  render() {
    // {new Date()} is not a valid react element. Rendering it will throw an error.
    return <p>Now:{new Date()}</p>;
  }
}
```

We need to implement an error handling mechanism to avoid crashes. React provides <a href="https://reactjs.org/docs/error-boundaries.html" target="_blank">error boundary apis</a> to handle such errors. So we refactor `MalformedComponent` as:

```js
class MalformedComponent extends React.Component {
  state = {
    error: null
  };

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { error };
  }

  render() {
    if (this.state.error) {
      return (
        <details>
          <summary>Ouch! Things are messed up. We are sorry. 👾</summary>
          <pre style={{ color: `red` }}>{this.state.error.stack}</pre>
        </details>
      );
    }
    return <WrappedComponent {...this.props} />;
  }
}
```

Adding error boundaries only fixes the `MalformedComponent`. We need to fix the other components too, means we need to add error boundaries to other components.

_How do we do it?_ Hmm, One way is to add the error handling code in every malformed component the way we did above. But it will make our component a bit cumbersome to maintain and less DRY.

_What if we write a function to fill in the error handling code?_ Well, we can write but we _shouldn't_ because we'll be modifying the existing component which is not recommended and may lead to unexpected behavior.

_What if we write a function which takes a malformed component and returns a new component which wraps the malformed component with error boundaries?_ Interesting! Only thing is, it will add a new wrapper component in our component tree, but we can live with it. Let's code it.

```js
const withErrorBoundaries = WrappedComponent => props => {
  return class extends React.Component {
    state = {
      error: null
    };

    static getDerivedStateFromError(error) {
      // Update state so the next render will show the fallback UI.
      return { error };
    }

    render() {
      if (this.state.error) {
        // Fallback ui.
        return (
          <details>
            <summary>Ouch! Things are messed up. We are sorry. 👾</summary>
            <pre style={{ color: `red` }}>{this.state.error.stack}</pre>
          </details>
        );
      }
      return <WrappedComponent {...this.props} />;
    }
  };
};
```

`withErrorBoundaries` can be used with any malformed component.

```js
const SafeComponent = withErrorBoundaries(MalformedComponent);
```

{% codepen https://codepen.io/smellycode/pen/mZMPBL %}


That's what precisely a higher order component is all about. It's a pattern which facilitates component logic reusability. You can think of a HOC as **a function that takes a component and returns a new component**. An in-depth explanation of HOCs is available <a href="https://reactjs.org/docs/higher-order-components.html" target="_blank">here</a>.

### Dumb Components

Dumb components are also known as _presentational_ or _stateless_ components. They mostly contain HTML and styles. The purpose of dumb components is to **render the DOM using _props_**. Dumb Components don't load or mutate any data. Data required by dumb components are passed as input/props along with the actions. That's why dumb components don't have any state related to data. It makes them more reusable and manageable. Here is a very basic `Greetings` dumb component :

```javascript
function Greetings(props) {
  return <h1>Hello {props.name}</h1>;
}
```

### Smart/Container Components

Smart components are also known as _Container Components_. Smart Components know how to load and mutate data. Sometimes smart components mere act as a container and pass data to child components as props. Smart Components can also have state and logic to update the state. A simple `Clock` component with state and logic.

```js
class Clock extends React.Component {
  state = { now: new Date() };

  intervalId = null;

  tick = () => this.setState({ now: new Date() });

  componentDidMount() {
    this.intervalId = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.intervalId);
  }

  render() {
    return <p>{this.state.now.toLocaleTimeString()}</p>;
  }
}
```

You can read more about <a href="https://www.shade.codes/dumb-components-and-smart-components/" target="_blank">Dumb Components and Smart components on Shade.codes</a>.