Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
let str = ReasonReact.string;
let url = "http://localhost:3000/users";
type user = {
id: int,
name: string,
};
type state =
| NotAsked
| Loading
| Failure
| Success(list(user));
module Decode = {
let user = user =>
Json.Decode.{
id: field("id", int, user),
name: field("name", string, user),
};
let users = json : list(user) => Json.Decode.list(user, json);
};
let fetchUsers = () =>
Js.Promise.(
Fetch.fetch(url)
|> then_(Fetch.Response.json)
|> then_(json =>
json |> Decode.users |> (users => Some(users) |> resolve)
)
|> catch(_err => resolve(None))
);
type action =
| LoadUsers
| LoadedUsers(list(user))
| LoadUsersFailed;
let component = ReasonReact.reducerComponent("FetchComponent");
let make = _children => {
...component,
initialState: () => NotAsked,
reducer: (action, _state) =>
switch (action) {
| LoadUsers =>
ReasonReact.UpdateWithSideEffects(
Loading,
(
self =>
Js.Promise.(
fetchUsers()
|> then_(result =>
switch (result) {
| Some(users) => resolve(self.send(LoadedUsers(users)))
| None => resolve(self.send(LoadUsersFailed))
}
)
|> ignore
)
),
)
| LoadedUsers(users) => ReasonReact.Update(Success(users))
| LoadUsersFailed => ReasonReact.Update(Failure)
},
render: self =>
switch (self.state) {
| NotAsked =>
<div>
(str("Click to start load Users"))
<button onClick=(_event => self.send(LoadUsers))>
(str("Load Users"))
</button>
</div>
| Loading => <div> (str("Loading...")) </div>
| Failure => <div> (str("Something went wrong!")) </div>
| Success(users) =>
<div>
<h2> (str("Users")) </h2>
<ul>
(
users
|> List.map(user =>
<li key=(string_of_int(user.id))> (str(user.name)) </li>
)
|> Array.of_list
|> ReasonReact.array
)
</ul>
</div>
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.