Getting started in Preact (by rebuilding a React app)
Tags: react, preact, tutorial, codenewbie
Published: 2020-11-30 20:46:32

A few weeks ago, after reading through the Preact docs, I decided to make a version of my React writing prompt generator in Preact to get more familiar with the library.

For those who haven’t heard of it (like I hadn’t!), Preact is a small, lightweight library with a lot of similar functionality to React, other than a few key differences. Preact more closely follows DOM specifications (e.g. it allows the use of `class` instead of `className`, though both are supported), and it uses the browser’s native event system instead of a synthetic one like React does, to name a couple. 

The Preact documentation states that it’s possible to move React apps over to Preact via [aliasing](https://preactjs.com/guide/v10/switching-to-preact#setting-up-compat) `react` and `react-dom` to `preact/compat` (short for compatibility), and it has some information on [how this is configured in various bundlers](https://preactjs.com/guide/v10/getting-started#aliasing-react-to-preact), but because I wanted to get more familiar with using Preact directly, I decided to start with Preact from the get-go and just move some of my code over manually instead. 

This is what I did! 

## 1. Start with the Preact CLI 

Following along with the [docs](https://preactjs.com/guide/v10/getting-started#best-practices-powered-by-preact-cli), I started by installing the Preact CLI on my computer, and then using it to create a new project: 

```
npm install -g preact-cli
```

```
preact create default preact-writing-prompt-generator
```

The `default` flag here refers to the default template for the Preact CLI, available on GitHub [here](https://github.com/preactjs-templates/default). I ended up having some minor issues with this set up later, but it was a good place to start because it gave me some code right out of the box that I could tinker with instead of building from scratch. 

Following along with the tutorial, I spun up a development server, and then started poking around the files. 

``` 
cd preact-writing-prompt-generator

npm run dev

```
From here, it was time to rebuild my components. 

## 2. JSX in Preact, and alternatives 

There are differences between React and Preact components, but not as many as I thought there would be going into this endeavour. Part of this is, of course, because while it doesn’t include every React feature (by design!), Preact was designed to achieve 100% compatibility with React with the `preact/compat` layer. 

Without using `preact/compat` though, I still had a few options for how to set up my Preact components. 

By default, React works with JSX, a syntactic extension to JavaScript that allows you to code what basically looks like HTML directly in JavaScript. Using JSX requires using a build step: the JSX code needs to be converted into JavaScript functions, which then make up the virtual DOM ([used to update the real DOM](https://medium.com/javascript-in-plain-english/what-the-heck-is-the-virtual-dom-3ef1ae4a950b)). 

Preact can be set up without using JSX, beneficial if you’d like to avoid a build step. 

This is an example of setting up Preact to work directly in the browser, without JSX, from the Preact [docs](https://preactjs.com/guide/v10/getting-started): 

```JavaScript
<script type="module">
  import { h, Component, render } from 'https://unpkg.com/preact?module';

  // Create your app
  const app = h('h1', null, 'Hello World!');

  render(app, document.body);
</script>
```

Preact components can also be built with Hyperscript/HTM, which is a syntax that looks similar to JSX but doesn’t require a build step (see another example from the Preact docs): 

```JavaScript
<script type="module">
  import { h, Component, render } from 'https://unpkg.com/preact?module';
  import htm from 'https://unpkg.com/htm?module';

  // Initialize htm with Preact
  const html = htm.bind(h);

  function App (props) {
    return html`<h1>Hello ${props.name}!</h1>`;
  }

  render(html`<${App} name="World" />`, document.body);
</script>
``` 

However, as I was already comfortable working in JSX from my experience with React, and as I wasn’t bothered by having a build step in this project, I decided to go with that. 

Without using `preact/compat` though, JSX still looks a little different in Preact. 

Basically, to use some more example code from the Preact docs, JSX that looks like this: 

```JavaScript
<a href="/">
  <span>Home</span>
</a>
```

would look like this in React when converted to function calls to build the virtual DOM: 

```JavaScript
React.createElement(
  'a',
  { href:'/' },
  React.createElement('span', null, 'Home')
);
```

and like this in Preact (without using `preact/compat`): 

```JavaScript
h(
  'a',
  { href:'/' },
  h('span', null, 'Home')
);
```

As far as I can tell, Preact uses a custom pragma ([a “directive” that tells a compiler how to handle the input](https://johno.com/jsx-pragma/)), named `h` by the creator of Preact because the original idea for a JSX-like builder function was called [hyperscript](https://github.com/dominictarr/hyperscript), to do pretty much the same thing React’s `React.createElement()` is doing. Because this function isn’t namespaced to Preact though, it has to be imported separately. 

What both of these ways of writing JSX have in common, is that they tell the transpiler (in this case it's Babel, which both React and this implementation of Preact use) that this `h` function should be called at runtime for each node.

## 3. Components 

With the way I was going to write my components figured out, I could start moving them over from my React project and editing them into Preact syntax! 

```JavaScript
import { h } from 'preact';
import { Router } from 'preact-router';

import Header from './header';
import Home from '../routes/home';
import Nautical from '../routes/nautical'
import About from '../routes/about'

const App = () => (
  <div id="app">
    <Header />
    <Router>
      <Home path="/" />
      <Nautical path="/nautical"/>
      <About path="/about"/>
    </Router>
  </div>
)

export default App;
```

This component imports `h` from Preact instead of `React` from React, but there aren’t any differences as to how that affects this component.

It also uses `preact-router` instead of `react-router-dom`, which does feature some different syntax. For example, in React, the routes in the code snippet above would be written like this: 

```JavaScript
// note that in React, Router is called Browser Router, but it is convention to import BrowserRouter as Router
<Router>
  <Route path=“/“><Home/></Route>
  <Route path=“/“><Nautical/></Route>
  <Route path=“/“><About/></Route>
</Router>
```

Other than that, Preact components can pretty much look like React components! 

## Conclusion 

Overall I really enjoyed the experience of translating the app I’d built into the Preact library! The main difficulty I ran into was figuring out how JSX worked in Preact, and that was mostly just to write this post—the Preact templates were intuitive to use even without that information. (Though on that note, thank you to Nick Taylor for sending me [this article](https://jasonformat.com/wtf-is-jsx/), which helped a lot!)

The other stumbling block for me was that the file structure in the Preact CLI was quite different from what I’m used to setting up for React projects. As far as I can tell that was specific to that template though, not related to the library itself, and I was still able to figure it out quite quickly even if it isn’t how I would usually set up my own project. 

I hope this post is useful to anyone else thinking of trying out Preact, and if you have questions, comments, or suggested corrections, please let me know in the comments!