A beginner's tutorial to Preact - Part 4: First steps with Preact
Tags: javascript, typescript, preact, jsx
Published: 2019-08-11 12:37:49

Now that we have reviewed everything we need to know prior to launching ourselves with Preact.

# What is Preact?

Preact is a 3kb library which allows developers to write applications using the same patterns we saw earlier. Preact provides its own implementation of the `h` function which outputs Virtual DOM (the "pure JavaScript representation of DOM nodes" we have talked about earlier), and uses an efficient rendering algorithm to try and make as few changes to the web page as possible. It also boasts many more features that we will look at later.

# The canonical "Hello World" application

## Dependencies

Let's start by creating a project. I'm going to use CodeSandbox (as I have already for the examples) as it allows me to embed the project into the post directly for you to run and tweak. So, either start a new "Vanilla (+ TS)" project, or start a new npm project (`npm init`).

The second thing to do, of course, is to install Preact. We're going to use version 10, which at the time of writing is still in Release Candidate, but is a complete rewrite of Preact itself, and writing a tutorial with a well known expire date isn't all that useful. Use `preact@next` if in beta, or just `preact` if you're reading this after version 10 was released as stable.

Next, if you're not using CodeSandbox, install Parcel as a development dependency: `npm i --save-dev parcel`, and optionally TypeScript (`npm i --save-dev typescript`). This is to replicate the CodeSandbox environment

## The index.html file

Next, we're going to need to create a basic index file for the browser to load - it will point to the script, and have an identified div element for us to render the application in.

CodeSandbox already provides that by default, although we'll need to change the script extension from `js` to `jsx` (or `ts` to `tsx`).

Here's the contents of `index.html`

```html
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div id="app"></div>

    <script src="src/index.tsx"></script>
  </body>
</html>

```

## The JavaScript entry-point of the application

Next, we need to create the file referenced in the script element - CodeSandbox users can rename the existing file in `src`, while local users can just create it at `src/index.jsx` or `src/index.tsx`.

Eitherway, if any, remove all contents, and let's start with our necessary imports:

```tsx
import {h, render} from "preact";
```

Here, we import Preact's implementation of the `h` function, and also a `render` function - we'll use that later.

### Our first component

Next, we need to write something for Preact to render. For this we need to write a **component**. We'll talk more about components in the next part, but in short, components are the reusable pieces of code that ca be passed props, and have state - they are the reusable elements that are at the base of reusability in modern JavaScript framework applications.

Components come in two variants - function-based, or class-based. More and more projects use function-based components, especially now that Hooks are getting more popular (more on that later). We'll use a function-based component, and name it `Application`. Let's add it in our `index` file:

```tsx
function Application() {
  return <p>Hello world!</p>;
}

```

That's it. This function accepts no props (as they are given through the arguments), and simply return a paragraph element (actually, it's Virtual DOM equivalent).

We need to use that new component somewhere, and that's why we also have imported the `render` function.

### Rendering our component

Since Preact deals with Virtual DOM through its `h` function, we need a way for that Virtual DOM to become, well, real. This is what the `render` function does - it inputs a Virtual DOM node, and a DOM element to insert the generated DOM into. We already have a div tag in our `index.html` made for the purpose of hosting our application - so let's use that. Then, we need a Virtual DOM node to pass into the render, and that Virtual DOM will come from our component. Remember that Preact's `h` function *returns* Virtual DOM, but what you may not know (but probably have guessed), is that the function can also take components instead of tag name as first parameter. This is how we reuse components in Preact. And, where we can use `h`, we can also write JSX - therefore that's how we'll pass the Application component to the render function.

Anyhow, let's get some generated DOM into our web page. We'll get a reference to the `<div id="app">` element in the DOM, and pass it to the `render` function:

```tsx
const root = document.getElementById("app");
render(<Application/>, root);
```

Our component displays "Hello World!" onto the web page! 🔥

{% codesandbox 2w5s9 %}

### Nesting components

Let's create *more components*, shall we?

Components are good for several things - but at their most basic, they allow to create reusable elements; for example, a button component we'll write next.

<!--
To keep things simple, this button component will be *very* basic, however in your own applications, this is where you would apply things like CSS styling, setup effects, among other things. Remember that components provide abstraction layers to your application in order to simplify building up the UI of your application. As such, you should see them as pieces of furniture that fit together into a whole, while also remember that the whole (the piece of furniture) fits into a bigger whole (a room) which itself fits a bigger whole (the house). We'll discuss guidelines about good practice on splitting up your UI into components that make sense.
-->

Leaving the implementation to next part, let's use this hypothetical Button component into our application. We want this component to be customizable to a certain degree, which can be done through propertiess. We can pass any value through those props, which includes functions (as [functions are values](https://www.oreilly.com/library/view/javascript-the-definitive/9781449393854/ch08s04.html)). This will be useful in keeping our Button component generic and therefore reusable - we will expose a "onClick" prop which expects a callback function which will get called when the user clicks on the component.

Let's use this specification for the accepted properties (often abbreviated as props) of this Button component:

```ts
interface ButtonProps {
  /** Any CSS color string, from names to hex codes to HSL, HSV or RGB(A) functions */
  color: string;
  /** Changes the button elevation by altering the shadow property of the button */
  elevated?: boolean;
  /** Callback function which gets called when the user clicks on the button */
  onClick?: (ev: MouseEvent) => void;
}
```

*Note: This is valid TypeScript which I use in the source code to define the component properties, see the CodeSandbox examples*

With this, we can create an application with two buttons to showcase how they can each be customized separatedly. In the following code, each button gets assigned a random color; the first button has a callback which shows an alert box on click while the second doesn't have any callback; also only the first button is elevated (as it is by default), the second button has its elevation turned off.

Below is the code with its accompanying CodeSandbox example:

```ts
function Application() {
  const color1 = colors[Math.round(Math.random() * colors.length)];
  const color2 = colors[Math.round(Math.random() * colors.length)];
  return (
    <div>
      <p>Hello world!</p>
      <Button color={color1} onClick={() => alert("First button was clicked!")}>
        Learn more
      </Button>
      <Button color={color2} elevated={true}>
        Another button
      </Button>
    </div>
  );
}
```

{% codesandbox cr5eo %}

# In the next part

We will look at how to implement this Button component (though you can peek into the CodeSandbox source code by yourself if you want to figure it out). We'll cover the two ways to write components, as well as several useful techniques.