Last active
February 8, 2021 02:38
-
-
Save pete-murphy/1c5c2f222f723acefae637df3f6df721 to your computer and use it in GitHub Desktop.
Routing example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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