Created
August 18, 2017 15:25
-
-
Save busypeoples/847d908ee0ed8e501883b04e0f554435 to your computer and use it in GitHub Desktop.
Displaying different UI States nicely in Reason
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
/* Slaying a UI Anti Pattern in Reason */ | |
type remoteData 'e 'a = | |
| Nothing | |
| Loading | |
| Failure 'e | |
| Success 'a; | |
type item = { | |
userId: int, | |
id: int, | |
title: string, | |
body: string | |
}; | |
let parseListJson json :item => { | |
userId: Json.Decode.field "userId" Json.Decode.int json, | |
id: Json.Decode.field "id" Json.Decode.int json, | |
title: Json.Decode.field "title" Json.Decode.string json, | |
body: Json.Decode.field "body" Json.Decode.string json, | |
}; | |
let parseListResponse json => Json.Decode.list parseListJson json; | |
let listUrl = "https://jsonplaceholder.typicode.com/posts?userId=1"; | |
let fetchList () => | |
Bs_fetch.fetch listUrl | |
|> Js.Promise.then_ Bs_fetch.Response.text | |
|> Js.Promise.then_ (fun jsonText => | |
Js.Promise.resolve (parseListResponse(Js.Json.parseExn jsonText)) | |
); | |
let se = ReasonReact.stringToElement; | |
let module RenderItems = { | |
let component = ReasonReact.statelessComponent "RenderItems"; | |
let make ::items _ => { | |
...component, | |
render: fun self => | |
<div className="items"> | |
(ReasonReact.arrayToElement | |
(Array.of_list | |
(List.map (fun item => <div | |
key=(string_of_int item.id) | |
> | |
(se item.title) | |
</div> | |
) items) | |
) | |
) | |
</div> | |
}; | |
}; | |
type state = { | |
items: remoteData string (list item), | |
}; | |
let handleListLoaded list _self => { | |
fetchList () | |
|> Js.Promise.then_ (fun items => { | |
ReasonReact.Update { | |
items: Success list | |
}; | |
Js.Promise.resolve (); | |
}) | |
|> ignore; | |
}; | |
let handleListOk state items _self => { | |
ReasonReact.Update { | |
...state, | |
items: Success items | |
}; | |
}; | |
let handleListError state e _self => { | |
ReasonReact.Update { | |
...state, | |
items: Failure e | |
}; | |
}; | |
let component = ReasonReact.statefulComponent "Data"; | |
let make _ => { | |
...component, | |
initialState: fun () => { | |
items: Nothing | |
}, | |
render: fun {state: {items}, update} => { | |
let view = switch (items) { | |
| Nothing => (se "Click to load data!") | |
| Loading => (se "Loading...") | |
| Failure e => (se e) | |
| Success items => <RenderItems items=items /> | |
}; | |
<div className="item"> | |
<div>view</div> | |
<br /> | |
<div> | |
<button | |
onClick=(update (fun text {state, update} => { | |
fetchList () | |
|> Js.Promise.then_ (fun items => { | |
(update (handleListOk state)) items; | |
Js.Promise.resolve (); | |
}) | |
|> Js.Promise.catch (fun _ => { | |
(update (handleListError state)) "Something went wrong!"; | |
Js.Promise.resolve(); | |
}); | |
ReasonReact.Update { | |
...state, | |
items: Loading | |
}; | |
})) | |
> | |
(se "click!") | |
</button> | |
</div> | |
</div> | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How about?
Where
'c
stands for cancel token, like in this example facebook/react#8883 (comment)