Skip to content

Instantly share code, notes, and snippets.

@lydell
Created January 6, 2024 10:34
Show Gist options
  • Save lydell/ae7f15bbc3881b907fcf447d0b80892e to your computer and use it in GitHub Desktop.
Save lydell/ae7f15bbc3881b907fcf447d0b80892e to your computer and use it in GitHub Desktop.
React-looking Elm code

React-looking Elm code

Terrible hacks to make Elm look like React.

{
"serve": ".",
"targets": {
"Hipster React App": {
"inputs": ["Main.elm"],
"output": "build/main.js"
}
}
}
{
"type": "application",
"source-directories": [
"."
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/html": "1.0.0",
"elm/json": "1.1.3"
},
"indirect": {
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.3"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}
<!DOCTYPE html>
<meta charset="UTF-8" />
<title>Hipster React App</title>
<div id="node"></div>
<script src="./build/main.js"></script>
<script>Elm.Main.init({ node })</script>
module Main exposing (main)
import React exposing (..)
import Zod
main = React.mount(render)
render(model) =
let
(getCount, setCount) = React.useState("count", Zod.int(), 0)
count = getCount(model)
in
ⲓᐸdivᐳ[
ⲓᐸbuttonᐳ { onClick = \() -> setCount(count - 1, model) }
"-"
ⲓᐸ𝘭ᐳ,
ⲓᐸspanᐳ (String.fromInt(count)) ⲓᐸ𝘭ᐳ,
ⲓᐸbuttonᐳ { onClick = \() -> setCount(count + 1, model) }
"+"
ⲓᐸ𝘭ᐳ
]ⲓᐸ𝘭ᐳ
{
"private": true,
"scripts": {
"start": "elm-watch hot"
},
"devDependencies": {
"elm": "0.19.1-6",
"elm-watch": "1.2.0-beta.5"
}
}
module React exposing (mount, useState, ⲓᐸ𝘭ᐳ, ⲓᐸbuttonᐳ, ⲓᐸspanᐳ, ⲓᐸdivᐳ)
import Html exposing (Html)
import Html.Attributes
import Html.Events
import Json.Decode
import Json.Encode
import Browser
mount(view) =
Browser.sandbox
{
init = Json.Encode.null,
update = always,
view = view
}
useState(name, codec, init) =
let
get(model) =
Json.Decode.decodeValue (optionalField name codec.decoder) model
|> Result.toMaybe
|> Maybe.andThen identity
|> Maybe.withDefault init
set(value, model) =
(Json.Decode.decodeValue (Json.Decode.keyValuePairs Json.Decode.value) model
|> Result.withDefault [])
++ [(name, codec.encoder value)]
|> Json.Encode.object
in
(get, set)
optionalField name decoder =
Json.Decode.maybe (Json.Decode.field name Json.Decode.value)
|> Json.Decode.andThen (\maybe ->
case maybe of
Just _ -> Json.Decode.field name decoder |> Json.Decode.map Just
Nothing -> Json.Decode.succeed Nothing
)
type End = End
ⲓᐸ𝘭ᐳ = End
ⲓᐸbuttonᐳ {onClick} text _ =
Html.button [Html.Events.onClick (onClick())] [ Html.text text ]
ⲓᐸspanᐳ text _ =
Html.span [] [ Html.text text ]
ⲓᐸdivᐳ children _ =
Html.div [] children
module Zod exposing (int)
import Json.Decode
import Json.Encode
int() =
{
encoder = Json.Encode.int,
decoder = Json.Decode.int
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment