Last active
July 29, 2020 23:47
-
-
Save isaacabraham/a81e1dede574f55257adff94208edb3e to your computer and use it in GitHub Desktop.
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
| // Boilerplate / "Frameworky" code | |
| module Safe = | |
| /// A function which, when given a model, will return a new model and a command, depending on the state of the server call. | |
| type CallHandler<'TModel, 'TMsg> = 'TModel -> 'TModel * Cmd<'TMsg> | |
| /// Represents a message which encapsulates a client / server call and response. | |
| type ServerMessage<'TModel, 'TMsg> = CallHandler<'TModel, 'TMsg> -> 'TMsg | |
| /// Makes a GET to a server endpoint and handles the outgoing request and incoming response. | |
| let inline Get<'TModel, 'TMsg> endpoint onDispatch onSuccess (serverCall:ServerMessage<'TModel,'TMsg>) input = | |
| let onLoaded entity model = onSuccess model entity, Cmd.none | |
| let loadCommand = Cmd.OfPromise.perform (endpoint >> Fetch.get<unit, _>) input (onLoaded >> serverCall) | |
| serverCall (fun model -> onDispatch model, loadCommand) | |
| // User code | |
| type Model = | |
| { IsLoading : bool | |
| TheCustomer : Customer option } | |
| type Msg = | |
| | LoadCustomer of Safe.CallHandler<Model, Msg> | |
| module Api = | |
| let getCustomerById = | |
| Safe.Get | |
| (sprintf "/api/customer/%i") // endpoint builder | |
| (fun model -> { model with IsLoading = true }) // on dispatch | |
| (fun model customer -> { model with IsLoading = false; TheCustomer = Some customer }) // on return | |
| LoadCustomer // wrapper message | |
| let init() = { TheCustomer = None; IsLoading = false }, Cmd.none | |
| let update msg model = | |
| match msg with | |
| | LoadCustomer handle -> handle model | |
| let view model dispatch = | |
| div [] [ | |
| button [ OnClick (fun _ -> dispatch (Api.getCustomerById 42)) ] [ str "Load Customer" ] | |
| div [] [ str (sprintf "Is Loading? %b" model.IsLoading) ] | |
| match model.TheCustomer with | |
| | Some c -> div [] [ str c.Name ] | |
| | None -> () | |
| ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment