Skip to content

Instantly share code, notes, and snippets.

@pete-murphy
Last active February 8, 2021 02:38
Show Gist options
  • Save pete-murphy/1c5c2f222f723acefae637df3f6df721 to your computer and use it in GitHub Desktop.
Save pete-murphy/1c5c2f222f723acefae637df3f6df721 to your computer and use it in GitHub Desktop.
Routing example
module Main where
import Prelude
import Data.Array (range)
import Data.Foldable (oneOf)
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Exception (throw)
import React.Basic (JSX, fragment)
import React.Basic.DOM (render)
import React.Basic.DOM as R
import React.Basic.Hooks (Component, component, useEffectOnce, useState', (/\))
import React.Basic.Hooks as React
import Routing.Hash (matches)
import Routing.Match (Match, end, int, lit, root)
import Web.HTML (window)
import Web.HTML.HTMLDocument (body)
import Web.HTML.HTMLElement (toElement)
import Web.HTML.Window (document)
main :: Effect Unit
main = do
body <- body =<< document =<< window
case body of
Nothing -> throw "Could not find body."
Just b -> do
app <- mkApp
render (app unit) (toElement b)
mkApp :: Component Unit
mkApp = do
postIndex <- mkPostIndex
post <- mkPost
postEdit <- mkPostEdit
component "App" \_ -> React.do
route /\ setRoute <- useState' (Just Home)
useEffectOnce do
matches appRoute \_ newRoute -> setRoute newRoute
pure
$ fragment
[ R.header_ [ headerNav ]
, case route of
Just Home -> R.h1_ [ R.text "Home" ]
Just PostIndex -> postIndex unit
Just (Post postId) -> post postId
Just (PostEdit postId) -> postEdit postId
Nothing -> R.h1_ [ R.text "Not found" ]
]
headerNav :: JSX
headerNav =
R.nav_
[ R.a
{ href: "#/posts"
, children: [ R.text "Posts" ]
}
, R.text " | "
, R.a
{ href: "#/"
, children: [ R.text "Home" ]
}
]
mkPostIndex :: Component Unit
mkPostIndex = do
component "PostIndex" \_ ->
pure $ R.ul_ $ range 1 10
<#> \n ->
R.li_
[ R.a
{ href: "#/posts/" <> show n
, children: [ R.text ("Post " <> show n) ]
}
]
mkPost :: Component Int
mkPost = do
component "Post" \n ->
pure
$ fragment
[ R.h1_ [ R.text ("Post " <> show n) ]
, R.p_
[ R.a
{ href: "#/posts/" <> show n <> "/edit"
, children: [ R.text "Click here" ]
}
, R.text " to edit this post"
]
]
mkPostEdit :: Component Int
mkPostEdit = do
component "PostEdit" \n ->
pure $ R.h1_ [ R.text ("Edit post " <> show n) ]
data AppRoute
= PostIndex
| Post Int
| PostEdit Int
| Home
appRoute :: Match (Maybe AppRoute)
appRoute =
oneOf
[ Just <$> postRoute
, Just <$> (root *> pure Home <* end)
, pure Nothing
]
where
postRoute =
root *> lit "posts"
*> oneOf
[ PostEdit <$> int <* lit "edit"
, Post <$> int
, pure PostIndex
]
<* end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment