aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHayleigh Thompson <me@hayleigh.dev>2024-03-24 21:17:38 +0000
committerHayleigh Thompson <me@hayleigh.dev>2024-03-24 21:17:38 +0000
commit65f32e8df1a49e469e559bda89bcc3279772d0d8 (patch)
tree2cb50fb04169a0c9a840baad9f1973824513d532
parent8eef034e6d7f551b5f092d87e54fa7a52da35b81 (diff)
downloadlustre-65f32e8df1a49e469e559bda89bcc3279772d0d8.tar.gz
lustre-65f32e8df1a49e469e559bda89bcc3279772d0d8.zip
:memo: Reword HTTP request example readme.
-rw-r--r--examples/05-http-requests/README.md80
1 files changed, 57 insertions, 23 deletions
diff --git a/examples/05-http-requests/README.md b/examples/05-http-requests/README.md
index f0ef1ee..e94fdbe 100644
--- a/examples/05-http-requests/README.md
+++ b/examples/05-http-requests/README.md
@@ -6,38 +6,61 @@
> Lustre is v3. To follow along with this guide, you need to _manually_ edit your
> `gleam.toml` and change the required version of lustre to `"4.0.0-rc.2"`.
-Up until now, all the logic in our examples has run neatly in a self-contained `Init -> Update 🔁 View` loop. But our applications often need to interact with the outside world, whether through browser APIs or HTTP requests.
+Up until now, we've seen Lustre applications constructed with the `lustre.simple`
+constructor. These kinds of applications are great for introducing the Model-View-Update
+(MVU) pattern, but for most real-world applications we'll need a way to talk to
+the outside world.
-For this, Lustre provides an `Effect` system. You should [read the docs on Lustre Effects](https://hexdocs.pm/lustre/4.0.0-rc1/lustre/effect.html) before continuing here.
+Lustre's runtime includes _managed effects_, which allow us to perform side effects
+like HTTP requests and communicate the results back to our application's `update`
+function. To learn more about Lustre's effect system and why it's useful, check
+out the [side effects guide](https://hexdocs.pm/lustre/guide/side-effects.html),
+or the docs for the [lustre/effect module](https://hexdocs.pm/lustre/lustre/effect.html)
+For now, we will focus on how to send HTTP requests in a Lustre application: a
+pretty important thing to know!
-... did you read the docs? Ok, let's move on!
+## Moving on from `lustre.simple`
-## The #(model, effect) Tuple
-You'll notice that running a Lustre app with side effects _changes the signature_ of our [`init`](src/app.gleam#L43) and [`update`](src/app.gleam#L54) functions. Instead of returning just a model, we return a tuple containing both a model and an `Effect(Msg)` value. The effect value specifies any further updates we might want the Lustre runtime to execute before the next invocation of the `view` function.
+From now on, the rest of these examples will use a different application constructor:
+[`lustre.application`]. Let's compare the type of both functions:
```gleam
-fn init(_) -> #(Model, Effect(Msg)) {
- #(Model(quote: None), effect.none())
-}
-
-fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
- case msg {
- Refresh -> #(model, get_quote())
- GotQuote(Ok(quote)) -> #(Model(quote: Some(quote)), effect.none())
- GotQuote(Error(_)) -> #(model, effect.none())
- }
-}
-
-fn get_quote() -> Effect(Msg) { ... }
+pub fn simple(
+ init: fn(flags) -> model,
+ update: fn(model, msg) -> model,
+ view: fn(model) -> Element(msg),
+) -> App(flags, model, msg)
+
+pub fn application(
+ init: fn(flags) -> #(model, Effect(msg)),
+ update: fn(model, msg) -> #(model, Effect(msg)),
+ view: fn(model) -> Element(msg),
+) -> App(flags, model, msg)
```
-> **Note:** Even in an app with side effects, the `view` function signature does not change. In Lustre, the view function is always [pure](https://en.wikipedia.org/wiki/Pure_function), accepting only a `Model` and returning only an `Element` without triggering any effects itself.
+All that's changed is the return type of our `init` and `update` functions. Instead
+of returning just a new model, they now return a tuple containing both a model and
+any side effects we want the runtime to perform.
-## HTTP Requests are Effects
+You'll notice that running a Lustre app with side effects _changes the signature_
+of our [`init`](src/app.gleam#L43) and [`update`](src/app.gleam#L54) functions.
+Instead of returning just a model, we return a tuple containing both a model an
+an `Effect(Msg)` value. The effect value specifies any further updates we might
+want the Lustre runtime to execute before the next invocation of the `view`
+function.
-As we touched on before, an HTTP Request is a form of effect, because it means our program needs to interact with the outside world.
+> **Note**: notice how the type of `view` remains the same. In Lustre, your `view`
+> is always a [_pure function_](https://en.wikipedia.org/wiki/Pure_function) that
+> takes a model and returns the UI to be rendered: we never perform side effects
+> in the `view` function itself.
-In this example, we use the great community library `lustre_http` to fetch a random quote whenever the user clicks the "New Quote" button. [Check out the lustre_http docs here.](https://hexdocs.pm/lustre_http/lustre_http.html)
+## HTTP requests as side effects
+
+The community library [`lustre_http`](https://hexdocs.pm/lustre_http/) gives us
+a way to model HTTP requests as Lustre `Effect`s. Crucially, when we call
+`lustre_http.get` we are _not_ performing the request! We're constructing a
+description of the side effect that we can hand off to the Lustre runtime to
+perform.
```gleam
fn get_quote() -> Effect(Msg) {
@@ -53,8 +76,19 @@ fn get_quote() -> Effect(Msg) {
}
```
-The `lustre_http.get(...)` function does a _lot_. That second parameter specifies not only what type of response to expect, but also how to decode it, what type to decode it _into_, as well as the `Msg` type that should be sent back to the Lustre runtime after it successfully executes.
+To construct HTTP requests, we need a few different things:
+
+- The `url` to send the request to.
+
+- A description of what we _expect_ the result to be. There are a few options:
+ `expect_anything`, `expect_text`, `expect_json`. In this example we say we're
+ expecting a JSON response and provide a decode.
+
+- A long with what we expect the response to be, we also need to provide a way
+ to turn that response into a `Msg` value that our `update` function can handle.
+The same applies for post requests too, but there you also need to provide the
+JSON body of the request.
## Getting help