Created
December 21, 2019 05:08
-
-
Save mlms13/28f94e74e62127de8c81fa5aa7d784e7 to your computer and use it in GitHub Desktop.
Request Weather Data using Relude
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
open Relude.Globals; | |
let baseUrl = "http://localhost:5050"; | |
// `getForecast` is an IO that will either succeed with decoded | |
// ForecastData or fail with a Fetch error. | |
// | |
// Since IO is inherently lazy, creating this value doesn't actually | |
// _do_ anything. Instead it needs to be run, which we do inside an | |
// `UpdateWithIO` return from a `useReducer` branch in our view. | |
let getForecast = | |
ReludeFetch.( | |
get(baseUrl ++ "/forecast/TOKEN/42.3601%2C-71.0589") | |
|> IO.flatMap(Response.StatusCode.ensure2xx) | |
|> IO.flatMap(Response.Json.decode(ForecastData.decode)) | |
); |
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
open Relude.Globals; | |
// We store our application state in a Relude AsyncResult, which is good at | |
// representing async data (that could fail) as a snapshot in time, using | |
// constructors like: | |
// | |
// - Init | |
// - Loading | |
// - Reloading(...) | |
// - Complete(Ok(...)) | |
// - Complete(Error(...)) | |
// | |
// If you've used RemoteData in Elm or PureScript, you may recognize this, | |
// but we capture failure with a Result and add a Reloading state | |
type state = AsyncResult.t(ForecastData.t, string); | |
type action = | |
| MakeRequest | |
| Succeed(ForecastData.t) | |
| Fail(string); | |
[@react.component] | |
let make = () => { | |
open ReludeReact; | |
let (state, dispatch) = | |
Reducer.useReducer( | |
_state => | |
fun | |
| Succeed(data) => Update(AsyncResult.ok(data)) | |
| Fail(err) => Update(AsyncResult.error(err)) | |
| MakeRequest => | |
UpdateWithIO( | |
Loading, | |
Api.getForecast() | |
|> IO.map(data => Succeed(data)) | |
|> IO.mapError(ReludeFetch.Error.show(_ => "Decode failure")) | |
|> IO.mapError(err => Fail(err)), | |
), | |
Init, | |
); | |
switch (state) { | |
| Init => | |
<button onClick={_ => dispatch(MakeRequest)}> | |
{React.string("Make Request!")} | |
</button> | |
| Loading | |
| Reloading(_) => React.string("loading") | |
| Complete(Ok({current, hourly})) => React.string(current.summary) | |
| Complete(Error(err)) => React.string("Something went wrong! " ++ err) | |
}; | |
}; |
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
/** | |
* This module defines our data types (which are closely related | |
* to the data structure exposed by the DarkSky API). Additionally, | |
* we have some helpers to construct and decode values from JSON. | |
*/ | |
module Conditions = { | |
type t = { | |
time: Js.Date.t, | |
summary: string, | |
icon: string, // TODO: enum of valid options | |
precipProbability: float, | |
temperature: float, | |
humidity: float, | |
}; | |
let make = (time, summary, icon, precipProbability, temperature, humidity) => { | |
time, | |
summary, | |
icon, | |
precipProbability, | |
temperature, | |
humidity, | |
}; | |
let decode = | |
Decode.AsResult.OfParseError.Pipeline.( | |
pure(make) | |
|> field("time", date) | |
|> field("summary", string) | |
|> field("icon", string) | |
|> field("precipProbability", floatFromNumber) | |
|> field("temperature", floatFromNumber) | |
|> field("humidity", floatFromNumber) | |
); | |
}; | |
type t = { | |
current: Conditions.t, | |
hourly: list(Conditions.t), | |
}; | |
let make = (current, hourly) => {current, hourly}; | |
let decode = | |
Decode.AsResult.OfParseError.Pipeline.( | |
pure(make) | |
|> field("currently", Conditions.decode) | |
|> at(["hourly", "data"], list(Conditions.decode)) | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@mlms13 anyway, how to use
Relude.debounce
withgetForecast
at this line https://gist.github.com/mlms13/28f94e74e62127de8c81fa5aa7d784e7#file-api-re-L11 or with caseuser type in
<input onChange={wantDebounceWithUpdateIO} />
Thanks before