Preact — Class Components and Fragments
Tags: webdev, programming, javascript, beginners
Published: 2021-01-22 21:38:11

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


Preact is a front end web framework that’s similar to React.

It’s smaller and less complex than React.

In this article, we’ll look at how to get started with front end development with Preact.

### Class Components

We can add class components as we do with React.

For example, we can write:

```
import { Component, render } from "preact";

class Clock extends Component {
  constructor() {
    super();
    this.state = { time: Date.now() };
  }

  componentDidMount() {
    this.timer = setInterval(() => {
      this.setState({ time: Date.now() });
    }, 1000);
  }

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

  render() {
    const time = new Date(this.state.time).toLocaleTimeString();
    return <span>{time}</span>;
  }
}
if (typeof window !== "undefined") {
  render(<Clock />, document.getElementById("root"));
}
```

We create the `Clock` component by creating a class that extends the `Component` class.

Then in the `constructor` , we create the `time` state and set it to `Date.now()` as the initial value.

The `componentDidMount` hook lets us initialize the data.

In the method, we call `setInterval` to create the timer and in the callback, we call `setState` to set the state.

`componentWillUnmount` is called when we unmount the component, so we call `clearInterval` to clear the timer when the component unmounts.

In the `render` method, we render the current time.

Preact methods include lifecycle methods that are included in React class components.

They include:

*   `componentDidMount() `— after the component gets mounted to the DOM
*   `componentWillUnmount()` — prior to removal from the DOM
*   `getDerivedStateFromProps(nextProps)` — just before `shouldComponentUpdate`. Use with care.
*   `shouldComponentUpdate(nextProps, nextState)` — before `render()`. Return `false` to skip render
*   `getSnapshotBeforeUpdate(prevProps, prevState)` — called just before `render()`. The return value is passed to `componentDidUpdate`.
*   `componentDidUpdate(prevProps, prevState, snapshot)` — after `render()`

### Fragments

We can use the `Fragment` component to render multiple components without a root element.

For example, we can write:

```
import { Fragment, render } from "preact";

function TodoItems() {
  return (
    <Fragment>
      <li>foo</li>
      <li>bar</li>
      <li>baz</li>
    </Fragment>
  );
}

const App = (
  <ul>
    <TodoItems />
    <li>qux</li>
  </ul>
);

if (typeof window !== "undefined") {
  render(App, document.getElementById("root"));
}
```

We have the `TodoItems` component, which renders a `Fragment` .

The resulting HTML only has the `li` elements.

In `App` , we combine `TodoItems` with `li` and render them together.

We can use `<>` and `</>` in place of `<Fragment>` and `</Fragment>` :

```
import { Fragment, render } from "preact";

function TodoItems() {
  return (
    <>
      <li>foo</li>
      <li>bar</li>
      <li>baz</li>
    </>
  );
}

const App = (
  <ul>
    <TodoItems />
    <li>qux</li>
  </ul>
);

if (typeof window !== "undefined") {
  render(App, document.getElementById("root"));
}
```

We can also return an array of components:

```
import { Fragment, render } from "preact";

function TodoItems() {
  return [<li>foo</li>, <li>bar</li>, <li>baz</li>];
}

const App = (
  <ul>
    <TodoItems />
    <li>qux</li>
  </ul>
);

if (typeof window !== "undefined") {
  render(App, document.getElementById("root"));
}
```

This is the same as what we have before.

If we use `Fragment` s in a loop, then we have to add the `key` prop and set it to a unique value so that the items can be distinguished:

```
import { Fragment, render } from "preact";

const items = [
  {
    id: 1,
    term: "apple",
    description: "red fruit"
  },
  {
    id: 2,
    term: "banana",
    description: "yellow fruit"
  }
];

function Glossary({ items }) {
  return (
    <dl>
      {items.map((item) => (
        <Fragment key={item.id}>
          <dt>{item.term}</dt>
          <dd>{item.description}</dd>
        </Fragment>
      ))}
    </dl>
  );
}

const App = (
  <div>
    <Glossary items={items} />
  </div>
);

if (typeof window !== "undefined") {
  render(App, document.getElementById("root"));
}
```

### Conclusion

We can create class components and fragments as we do with React.