Skip to content

Instantly share code, notes, and snippets.

@shrynx
Created December 30, 2018 16:15
Show Gist options
  • Save shrynx/9efe159979fb5f0c52ee87eaa8a49e15 to your computer and use it in GitHub Desktop.
Save shrynx/9efe159979fb5f0c52ee87eaa8a49e15 to your computer and use it in GitHub Desktop.
module type Res = {type t;};
module Make = (R: Res) => {
include R;
type state =
| NotAsked
| Loading
| NetworkError
| DecodingError
| Data(t);
type action =
| Skip
| Init
| NetworkFail
| DecodeingFail
| Loaded(t);
let component = ReasonReact.reducerComponent("FetchWith");
let make = (~req, ~skip=false, ~render, _children) => {
...component,
initialState: _state => NotAsked,
reducer: (action, _state) =>
switch (action) {
| Skip => ReasonReact.Update(NotAsked)
| Init =>
ReasonReact.UpdateWithSideEffects(
Loading,
(
self =>
Js.Promise.(
req()
|> then_(response =>
Belt.Result.mapWithDefault(
response, self.send(DecodeingFail), data =>
self.send(Loaded(data))
)
|> resolve
)
|> catch(_ => resolve(self.send(NetworkFail)))
|> ignore
)
),
)
| Loaded(data) => ReasonReact.Update(Data(data))
| DecodeingFail => ReasonReact.Update(DecodingError)
| NetworkFail => ReasonReact.Update(NetworkError)
},
didMount: self => skip ? self.send(Skip) : self.send(Init),
render: ({state}) =>
switch (state) {
| NotAsked => ReasonReact.null
| _ => render(state)
},
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment