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.
permalinkSpago
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">
<head>
<meta charset="UTF-8" />
<title>PureScript React App</title>
</head>
<body>
<div id="root"></div>
<script src="/index.js"></script>
</body>
</html>
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!