Skip to content

Instantly share code, notes, and snippets.

@Abdisalan
Created November 15, 2019 03:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Abdisalan/b7f9ffc8bde730729865463b7d46ec6a to your computer and use it in GitHub Desktop.
Save Abdisalan/b7f9ffc8bde730729865463b7d46ec6a to your computer and use it in GitHub Desktop.
Reason React Component Example
type post = {
img: string,
title: string,
alt: string,
};
module Decode = {
let post = post =>
Json.Decode.{
img: field("img", string, post),
title: field("safe_title", string, post),
alt: field("alt", string, post),
};
};
let fetchPost = () => {
Random.init(int_of_float(Js.Date.now()));
let postID = Random.int(2224); /* how many posts as of Nov 6, 2019 */
Js.Promise.(
Fetch.fetch("https://xkcd.now.sh/?comic=" ++ string_of_int(postID))
|> then_(Fetch.Response.json)
|> then_(json => json |> Decode.post |> (post => Some(post) |> resolve))
|> catch(_err => resolve(None))
);
};
type state =
| NotAsked
| Loading
| Failure
| Success(post);
type action =
| RequestPost
| LoadedPost(post)
| LoadPostFailed;
let reducer = (_state, action) =>
switch (action) {
| RequestPost => Loading
| LoadedPost(post) => Success(post)
| LoadPostFailed => Failure
};
[@react.component]
let make = () => {
let (state, dispatch) = React.useReducer(reducer, NotAsked);
React.useEffect1(
() =>
if (state == Loading) {
Js.Promise.(
fetchPost()
|> then_(result =>
switch (result) {
| Some(users) => resolve(dispatch(LoadedPost(users)))
| None => resolve(dispatch(LoadPostFailed))
}
)
|> ignore
);
None;
} else {
None;
},
[|state|],
);
switch (state) {
| NotAsked =>
<>
<button onClick={_event => dispatch(RequestPost)}>
{ReasonReact.string("Random Post")}
</button>
</>
| Loading => <> {ReasonReact.string("Loading")} </>
| Failure => <> {ReasonReact.string("Failed to load post")} </>
| Success(post) =>
<>
<button onClick={_event => dispatch(RequestPost)}>
{ReasonReact.string("Random Post")}
</button>
<h2> {ReasonReact.string(post.title)} </h2>
<img width="100%" src={post.img} alt={post.title} title={post.alt} />
</>
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment