permalinkGetting Started with PureScript and React

This tutorial will walk you through installing all the machinery, so you can focus on writing actual code. By the end of it we'll have a Hello World style React app written in PureScript.

permalinkInstalling tooling

I will assume you have npm installed. If not, here's how to install it.


PureScript has an excellent package manager called Spago. We can easily install it with npm.

npm install -g spago

permalinkAn editor of your choice

PureScript has support for many editors. I recommend IntelliJ IDEA with the PureScript plugin. You can also use VSCode with the PureScript IDE plugin. Finally, if you'd like to drastically increase the chance of not finishing this tutorial, you can use VIM or Emacs.

permalinkCreating a new project

We can create a new project with spago init.

mkdir purescript-react-app
cd purescript-react-app
spago init

Now we have the PureScript part done. However, since we want to use a JavaScript library (namely, react), we also need to create a package.json file.

This is about as easy and goes:

npm init -y

permalinkInstalling dependencies

We will need to install a few dependencies:

npm install react react-dom
spago install react-basic react-basic-dom react-basic-hooks

You can now build the PureScript part with

spago bundle-app

After running this command there should be a index.js file at the root of the project. We've told spago to take our Main.purs file and compile it to JavaScript that runs its main function.

permalinkMaking a webpage

Let's create the following index.html file in our project root:

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8" />
    <title>PureScript React App</title>
    <div id="root"></div>
    <script src="/index.js"></script>

This is the shell of our website. We will be rendering our app into the <div> where id is "root". Note how the <script> tag references the compiled JavaScript code from the previous step. If you open this file in a browser, you will see a blank page. Let's change that.

permalinkFinding the root and rendering hello world

Replace the Main.purs file with this:

module Main where

import Prelude
import Effect (Effect)
import Web.HTML (window)
import Data.Maybe (Maybe, Maybe(..))
import Web.DOM.Internal.Types (Element)
import Web.HTML.Window (document)
import Web.HTML.HTMLDocument (toNonElementParentNode) as HTMLDocument
import Web.DOM.NonElementParentNode (getElementById)
import Data.Foldable (for_)
import React.Basic.DOM.Client as ReactDOM
import React.Basic.DOM (text) as R
import Effect.Console (error) as Console

main :: Effect Unit
main = do
  maybeRootElement <- findElementByIdInDocument "root"
  case maybeRootElement of
    Nothing -> Console.error "Could not find element with id 'root'"
    Just rootElement -> do
      reactRoot <- ReactDOM.createRoot rootElement
      ReactDOM.renderRoot reactRoot $ R.text "Hello, React"

findElementByIdInDocument  String  Effect (Maybe Element)
findElementByIdInDocument id = do
  win ← window
  doc ← document win
  let node = HTMLDocument.toNonElementParentNode doc
  getElementById id node

It goes through the DOM API and finds the element with the id "root", then creates a React root and renders a text node into it.

permalinkTry it out

If we run spago bundle-app now again, spago will tell us that we use some dependencies that we're not explicitly declaring. Fortunately it prints the exact command we need to run to fix this:

spago install foldable-traversable maybe web-dom web-html

If we do it now again:

spago bundle-app
npx http-server

We can open http://localhost:8080 and see our app running!

Just look at it!

PureScript React App
Hello React!