Getting up and running with Reason, React, and Parcel
Tags: reason, react, parcel
Published: 2019-02-19 04:08:21

---
title: Getting up and running with Reason, React, and Parcel
published: true
description: Learn how to set up a Reason React project with Parcel.
tags: reasonml, react, parcel
---

#### UPDATED: 4/23/2019
Recently the Reason React project released new bindings. It uses a new version of "react-jsx", and utilizes the React Hooks API instead of the old record based API.

This means that if you have experience with hooks, you'll feel pretty much right at home with Reason React, with some small differences. 

---
With the rise of TypeScript on the front end, I think there will be an increased willingness to learn and utilize typed, compile-to-javascript languages. One strong contender for me is Reason.

You may have heard about Reason and thought about learning it, but it's hard to give up the JavaScript tools you already know and love. The good news is that Bucklescript and tools like Parcel make Reason a breeze to work with.

The following will show you how to set up a Reason React project with Parcel, but teaching you Reason, or how Reason React works compared to React in JavaScript are outside of the scope of this article. If you'd like to learn more about those things, let me know in the comments and I'll gladly write more.

---
## Quick Background

### What is Reason?
Reason is a special syntax that will look extremely familiar to JavaScript programmers, that uses OCaml under the hood.

### Why does Reason use OCaml under the hood?
Facebook has been using OCaml for a long time to write some of their internal tools (Flow is written in OCaml). OCaml is a fast, mature language that has great type inference, strong type safety, and can compile to many different targets including JavaScript, and Native.

### What is Bucklescript?
Bucklescript is a compiler that takes OCaml (or Reason), and turns it into highly optimized, and surprisingly readable JavaScript. 

### What will we be using today?
The set up we are using will use Reason as the language of our code, reason-react as the front-end framework, Bucklescript for compiling our Reason code to JavaScript, and Parcel for bundling everything up.

### Expectations
To get the most out this, you'll want to be comfortable with React.

---
## Initialization

The first we are going to do is make a new folder for our project, and change into the directory.

```sh
mkdir reason-parcel
cd reason-parcel

```

Then we are going to initialize using either npm, or yarn, and install all of our dependencies.

To use the new Reason React bindings you'll want to make sure that you are using bs-platform \^5.0.0, and reason-react \^7.0.0.

```sh
yarn init -y 
yarn add -D parcel-bundler bs-platform bsb-js
yarn add react react-dom reason-react
```
---

## Scripts
Now open up your package.json file, and we are going to add a start script. Add the following to the bottom of your package.json
```json
{
    "scripts": {
        "start": "parcel src/index.html"
    }
}
```
---
## Set up index.html

Let's make a directory called `src`. We need to make an `index.html` file inside of `src` to match the start script we added to the package.json. While we're at it, we might as well make the file where our Reason code will live.

```sh
mkdir src
touch src/index.html
touch src/Main.re
```

You can use whatever HTML boilerplate you'd like. I highly recommend emmet, and if you use VSCode it's already available. Or you can copy the following:

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>

</body>
</html>

```

Inside the `<body>` tag of index.html add:
```html
  <div id="app"></div>
  <script src="./Main.re"></script>

```

There are two important things to note:
1. The id of the div is "app". This will be used later inside of our Main.re file to render our app.
2. The src property on our script element coincides to the name of the file we just created. Parcel is smart enough to see this src, and know that it needs to process the Reason file, and replace the src property with the outputted JavaScript file path.

---

## Set up bsconfig.json

In the root of your project make a file called `bsconfig.json`. 

```sh
touch bsconfig.json
```

Bucklescript will read from this file for configuration. If you want to read more about all of the available options for the config file, Bucklescript has [great documentation](https://bucklescript.github.io/docs/en/build-configuration.html).

Copy the following config into bsconfig.json
```json
{
    "name": "reason-parcel",
    "reason": {
        "react-jsx": 3
    },
    "version": "0.1.0",
    "sources": [{
        "dir": "src",
        "subdirs": true
    }],
    "package-specs": {
        "module": "commonjs",
        "in-source": true
    },
    "suffix": ".bs.js",
    "bs-dependencies": ["reason-react"],
    "refmt": 3
}
```

Let's go through some of the interesting properties:

* reason
    * reason-react: Is set to 3 to allow the new JSX features.
* sources
    * dir: Is set to the `src` folder we made earlier.
    * subdirs: Is true because this tells Bucklescript to recursively check within our `src` folder for Reason files.
* `package-specs`
    * module: commonjs is the default 👍 which is good enough for us. 
    * in-source: Will make our outputted JavaScript files appear next to their Reason counterparts.
* bs-dependencies: This is an array of the Reason specific libraries you depend on. Right now we are only using `reason-react`, but you could use component libraries, styling libraries, etc.
* refmt: should be set to 3 for the ReasonV3 syntax. 

---

## Let's Finally Write Some Reason

Now with all of that out of the way, let's write some Reason code, and view it in the browser!

Open up src/Main.re and copy the following exactly. Semi-colons, double-quotes, and all. We'll run through exactly what is happening shortly.
```ocaml

module HelloWorld = {
   [@react.component]
    let make = () => <h1>{React.string("Hello, World!")}</h1>
};

ReactDOMRe.renderToElementWithId(<HelloWorld />, "app");

```

Now save the file, and run `yarn start` or `npm run start`, and open up [localhost:1234/](localhost:1234/)

Alright so there's a few things that are probably familiar, and a few things that are probably weird.

### The Familiar

#### Rendering to element with a specific id:
```ocaml
ReactDOMRe.renderToElementWithId(<HelloWorld />, "app");
```
That should look pretty familiar to you if you've written React before. It's essentially doing the same as:
```jsx
ReactDOM.render(<HelloWorld/>, document.getElementById("app"));
```

#### JSX

For the most part, JSX in Reason is the exact same. There are some small caveats to HTML attributes that name-clash with Reason reserved words like the `type` property on input elements becomes `type_`.

### The Weird

#### What is with the `module` declaration? 

```ocaml

module HelloWorld = {
};
```

The full explanation goes a little deeper than the scope of this article, but in Reason a file is automatically a module. 

To create components in Reason React you need to either declare each new component in a new module, or in a new file. By wrapping our component in `module HelloWorld ={};` it allows us to use the JSX element `<HelloWorld />`.

#### What is this [@react.component]?

This is the recommended way to make a new Reason React component. It does some stuff for us behind the scenes which makes our lives easier, but if you want to learn how to manually create your own components without it, check out the new page on components in the [Reason React documentation](https://reasonml.github.io/reason-react/docs/en/components).

#### What is the `make` function?

```ocaml
let make = () => <h1>{React.string("Hello from Reason")}</h1>
```

Similar to how in React class components React looks for a render method, in a Reason React module, Reason React expects a make function. This make function will take all of the `props` as an argument, and simply return some JSX.

#### Is that really what I have to do to make strings?
```ocaml
React.string("Hello, from Reason")
```

Yes. Yes it is. At least that it is how you have to make strings that are valid Reason React elements. Stay tuned for the next section for some tips to make strings in Reason React less painful. 

--- 
## Let's Refactor a Little

First let's pull out our component and put it in its own file.

```sh
touch src/HelloWorld.re

```
Then we can copy and paste the HelloWorld module, but this time because it's in its own file so we don't need to wrap it in a `module`.

Inside of HelloWorld.re
```ocaml
let s = React.string;

[@react.component]
let make = () => <h1>{s("Hello, from Reason")}</h1>;

```

I also made it easier to call `React.string` by assigning it to a short variable, `s`. This technique is something you'll see quite frequently in Reason React code. 

Now let's go back to our `Main.re` file and delete everything besides the last line.

Main.re
```ocaml
ReactDOMRe.renderToElementWithId(<HelloWorld />, "app");
```

Notice how we didn't have to explicitly import `HelloWorld` into `Main.re`? This will seem extremely weird at first, but because of how OCaml's module system works, all file-level modules are globally available under the file name.

So in `Main.re` we have access to the HelloWorld module. By using it in our JSX Reason React knows to call the module's `make` function. 

---

Now you have all of the pieces necessary for starting a Reason React project with Parcel. Feel free to play around with things, and let me know what questions you have regarding Reason, Reason React, or Parcel.

P.S. I wouldn't feel right without quickly mentioning `bsb` as an alternative for bootstrapping Reason React projects:
```sh
bsb -theme react -init <PROJECT_NAME>
```

To use the `bsb` command you will have to install it globally
```sh
yarn global add bsb
```
Or use npx (if you're using npm 5.2 or newer you already have it installed) to run the command
```sh
npx bsb -theme react -init <PROJECT_NAME>
```