From 4d04169a26c8d46c21d6efbdc285c3a360d8c441 Mon Sep 17 00:00:00 2001 From: Teymour Aldridge Date: Thu, 16 Apr 2020 12:41:04 +0100 Subject: [PATCH 01/16] Added explanation of the fetch module. --- src/concepts/services/fetch.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/concepts/services/fetch.md diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md new file mode 100644 index 0000000..b0fc36e --- /dev/null +++ b/src/concepts/services/fetch.md @@ -0,0 +1,24 @@ +# Fetch +## Introduction +The format module can be used to make requests to a server. This allows a Yew application to connect to a backend. + +## Making requests +### Building requests +Before you can send a request to the server, you need to construct it. This should be done using the `yew::services::fetch::Request` object. +```rust +use yew::services::fetch::Request; +use yew::format::Nothing; +let get_request = Request::get("https://example.com/api/v1/something").body(Nothing).expect("Could not build that request") +``` + +```rust +use yew::services::fetch::Request; +use yew::format::Json; +use serde_json::json; +let post_request = Request::post("https://example.com/api/v1/post/something").header("Content-Type", "application/json").body(Json(&json!({"key": "value"}))).expect("Could not build that request.") +``` +### Dispatching requests +To dispatch requests an instance of the `fetch_service` is needed. This can be created using `yew::services::FetchService::new()`. After building a request, it can be dispatched using `FetchService`'s `fetch` method. This method takes two arguments: a request and a `ComponentLink` callback with a closure taking an instance of `yew::services::fetch::Response`. This closure is run after the request finishes and can be used to initiatiate a redraw of the component by returning a message. + +## Further reading +* [The API documentation](https://docs.rs/yew/0.14.3/yew/services/fetch/index.html) From 4b53d408e6d4c4f16e05b171c475b70c3de39aaa Mon Sep 17 00:00:00 2001 From: Teymour Aldridge Date: Sun, 19 Apr 2020 11:14:56 +0100 Subject: [PATCH 02/16] Add further reading. --- src/concepts/services/fetch.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index b0fc36e..2514a44 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -1,10 +1,10 @@ # Fetch ## Introduction -The format module can be used to make requests to a server. This allows a Yew application to connect to a backend. +The fetch module can be used to make requests to a server. This allows a Yew application to connect to a backend. ## Making requests ### Building requests -Before you can send a request to the server, you need to construct it. This should be done using the `yew::services::fetch::Request` object. +Before you can send a request to the server, you need to construct the request. This should be done using the `yew::services::fetch::Request` object. ```rust use yew::services::fetch::Request; use yew::format::Nothing; @@ -22,3 +22,4 @@ To dispatch requests an instance of the `fetch_service` is needed. This can be c ## Further reading * [The API documentation](https://docs.rs/yew/0.14.3/yew/services/fetch/index.html) +* The [dashboard](https://github.com/yewstack/yew/tree/master/examples/dashboard) and [npm_and_rest](https://github.com/yewstack/yew/tree/master/examples/web_sys/npm_and_rest) examples. From 4ad3a66242441d1fedfb1cd2d7719b29da3f9d4b Mon Sep 17 00:00:00 2001 From: Teymour Aldridge Date: Sun, 19 Apr 2020 12:38:29 +0100 Subject: [PATCH 03/16] Added example closure for error handling. --- src/concepts/services/fetch.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index 2514a44..0c7640f 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -20,6 +20,22 @@ let post_request = Request::post("https://example.com/api/v1/post/something").he ### Dispatching requests To dispatch requests an instance of the `fetch_service` is needed. This can be created using `yew::services::FetchService::new()`. After building a request, it can be dispatched using `FetchService`'s `fetch` method. This method takes two arguments: a request and a `ComponentLink` callback with a closure taking an instance of `yew::services::fetch::Response`. This closure is run after the request finishes and can be used to initiatiate a redraw of the component by returning a message. +The `Response` type takes a generic `Result` as a type argument. You should specify types for your callback closure; any type can be used as long as it implements `From` (`Text` is a type from the format module), this can be achieved by deriving serde's `Deserialize`. + +An example closure which could be used: +```rust +|response: Response>| -> Msg { + match response { + Ok(response) => { + // handle response here + } + Err(e) => { + // handle errors here + } + } +} +``` + ## Further reading * [The API documentation](https://docs.rs/yew/0.14.3/yew/services/fetch/index.html) * The [dashboard](https://github.com/yewstack/yew/tree/master/examples/dashboard) and [npm_and_rest](https://github.com/yewstack/yew/tree/master/examples/web_sys/npm_and_rest) examples. From 55a2d8e3ab521573b0d50faadf7f11fe249dd1e9 Mon Sep 17 00:00:00 2001 From: Teymour Aldridge Date: Fri, 1 May 2020 09:34:10 +0100 Subject: [PATCH 04/16] Added functional example. --- src/concepts/services/fetch.md | 136 +++++++++++++++++++++++++++++---- 1 file changed, 121 insertions(+), 15 deletions(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index 0c7640f..9855573 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -1,16 +1,15 @@ -# Fetch +# The Fetch Service ## Introduction -The fetch module can be used to make requests to a server. This allows a Yew application to connect to a backend. +The fetch module can be used to make requests to a server. This allows a Yew application to connect to a backend and provide interactive functionality. ## Making requests ### Building requests -Before you can send a request to the server, you need to construct the request. This should be done using the `yew::services::fetch::Request` object. +Yew has a struct `Request` (which comes from the `http` crate) that is used to 'build' requests before they can be dispatched to a server. The body type of the request must have the trait `Into`. ```rust use yew::services::fetch::Request; use yew::format::Nothing; -let get_request = Request::get("https://example.com/api/v1/something").body(Nothing).expect("Could not build that request") +let get_request = Request::get("https://example.com/api/v1/get/something").body(Nothing).expect("Could not build that request") ``` - ```rust use yew::services::fetch::Request; use yew::format::Json; @@ -18,19 +17,126 @@ use serde_json::json; let post_request = Request::post("https://example.com/api/v1/post/something").header("Content-Type", "application/json").body(Json(&json!({"key": "value"}))).expect("Could not build that request.") ``` ### Dispatching requests -To dispatch requests an instance of the `fetch_service` is needed. This can be created using `yew::services::FetchService::new()`. After building a request, it can be dispatched using `FetchService`'s `fetch` method. This method takes two arguments: a request and a `ComponentLink` callback with a closure taking an instance of `yew::services::fetch::Response`. This closure is run after the request finishes and can be used to initiatiate a redraw of the component by returning a message. +The `FetchService` provides a binding to the browser's `fetch` API. Requests can be sent using either `FetchService::fetch` or `FetchService::fetch_with_options` (`fetch_with_options` should be used where cookies need to be sent in a request). -The `Response` type takes a generic `Result` as a type argument. You should specify types for your callback closure; any type can be used as long as it implements `From` (`Text` is a type from the format module), this can be achieved by deriving serde's `Deserialize`. +`FetchService::fetch` accepts two parameters: a `Request` object and a `Callback`. The closure with which the callback is constructed must take a single parameter of type `Response`. `Response` accepts a type argument – the type must implement `From`. -An example closure which could be used: -```rust -|response: Response>| -> Msg { - match response { - Ok(response) => { - // handle response here +{% hint style="info" %} +If you keep getting an error saying that "the operation was aborted" or "Error 408" this might be because the [CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) of the website you are trying to access are not set correctly. +{% endhint %} + +```rust +use yew::prelude::*; +use yew::services::fetch::{FetchService, FetchTask}; +use serde::Deserialize; + +#[derive(Debug, Clone)] +struct FetchServiceExample { + fetch_service: FetchService, + ft: Option, + iss: Option, + link: ComponentLink +} + +#[derive(Deserialize, Debug, Clone)] +struct ISSPosition { + latitude: String, + longitude: String +} + +#[derive(Deserialize, Debug, Clone)] +struct ISS { + message: String, + timestamp: i32, + iss_position: ISSPosition, + fetching: bool +} + +#[derive(Debug, Clone)] +enum Msg { + GetLocation, + Noop, + ReceiveLocation(ISS) +} + +impl Component for FetchServiceExample { + type Message = Msg; + type Properties = (); + fn create(_: Self::Properties, link: ComponentLink) -> Self { + Self { + fetch_service: FetchService::new(), + ft: None, + iss: None, + link, + fetching: false } - Err(e) => { - // handle errors here + } + fn change(&mut self, _: Self::Properties) -> bool { + unimplemented!() + } + fn update(&mut self, msg: Self::Message) -> bool { + match msg { + GetLocation => { + // 1. build the request + let request = Request::get("http://api.open-notify.org/iss-now.json") + .body(Nothing) + .expect("Could not build request."); + // 2. construct a callback + let callback = self.link.callback(|response: Response>>| { + // split up the response into the HTTP data about the request result and data from the request + let (meta, Json(data)) = response.into_parts(); + if meta.status.is_success() { + match data.message { + "success" => { + Self::Message::ReceiveLocation(data.clone()) + } + _ => { + Self::Message::Noop + } + } + } else { + Self::Message::Noop + } + }); + // 3. pass the request and callback to the fetch service + self.fetch_service.fetch(request, callback); + self.fetching = true; + // we want to redraw so that the page displays a 'fetching...' message to the user + true + } + Self::Message::ReceiveLocation(location) => { + self.iss = location; + self.fetching = false; + // we want to redraw so that the page no longer says 'fetching...' + true + } + _ => false + } + } + fn view(&self) -> Html { + html! { + <> + {if self.fetching { + html! {

{"Fetching data..."}

} + } else { + html! {

} + }} + { + match self.iss { + Some(space_station) => html! { +

{"The ISS is at:"}

+

{format!("Latitude: {}", space_station.iss_location.latitude)}

+

{format!("Longitude: {}", space_station.iss_location.longitude)}

+ } + None => html! { + + } + } + } + + } } } From d9ae58db48deebc207b70ec11970f35fab891f9b Mon Sep 17 00:00:00 2001 From: Teymour Aldridge <42674621+teymour-aldridge@users.noreply.github.com> Date: Sat, 2 May 2020 14:37:43 +0100 Subject: [PATCH 05/16] Create `FetchService` on the fly. Co-authored-by: Justin Starry --- src/concepts/services/fetch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index 9855573..b2e3407 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -99,7 +99,7 @@ impl Component for FetchServiceExample { } }); // 3. pass the request and callback to the fetch service - self.fetch_service.fetch(request, callback); + FetchService::new().fetch(request, callback); self.fetching = true; // we want to redraw so that the page displays a 'fetching...' message to the user true From 38c39bd4f950cb51f503d9890beb03ed30ac46a8 Mon Sep 17 00:00:00 2001 From: Teymour Aldridge <42674621+teymour-aldridge@users.noreply.github.com> Date: Sat, 2 May 2020 14:38:04 +0100 Subject: [PATCH 06/16] Remove unnecessary `fetch_service` field. Co-authored-by: Justin Starry --- src/concepts/services/fetch.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index b2e3407..e5ac55c 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -32,7 +32,6 @@ use serde::Deserialize; #[derive(Debug, Clone)] struct FetchServiceExample { - fetch_service: FetchService, ft: Option, iss: Option, link: ComponentLink From 6a56bf8a365853d0b094393ec2fa5d7a9b6c0e48 Mon Sep 17 00:00:00 2001 From: Teymour Aldridge <42674621+teymour-aldridge@users.noreply.github.com> Date: Sat, 2 May 2020 14:38:32 +0100 Subject: [PATCH 07/16] Remove redundant `fetch_service` field. Co-authored-by: Justin Starry --- src/concepts/services/fetch.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index e5ac55c..f6b86b8 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -63,7 +63,6 @@ impl Component for FetchServiceExample { type Properties = (); fn create(_: Self::Properties, link: ComponentLink) -> Self { Self { - fetch_service: FetchService::new(), ft: None, iss: None, link, From 9e454bef55d1abe0f58192a4726bacdfdf1fa0dc Mon Sep 17 00:00:00 2001 From: Teymour Aldridge <42674621+teymour-aldridge@users.noreply.github.com> Date: Sat, 2 May 2020 14:39:02 +0100 Subject: [PATCH 08/16] Update src/concepts/services/fetch.md Co-authored-by: Justin Starry --- src/concepts/services/fetch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index f6b86b8..08aea92 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -70,7 +70,7 @@ impl Component for FetchServiceExample { } } fn change(&mut self, _: Self::Properties) -> bool { - unimplemented!() + false } fn update(&mut self, msg: Self::Message) -> bool { match msg { From cb60e6df1b10c914b74a2b3890298073e4004fa9 Mon Sep 17 00:00:00 2001 From: Teymour Aldridge <42674621+teymour-aldridge@users.noreply.github.com> Date: Sat, 2 May 2020 14:40:26 +0100 Subject: [PATCH 09/16] Update src/concepts/services/fetch.md Co-authored-by: Justin Starry --- src/concepts/services/fetch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index 08aea92..6d176aa 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -102,7 +102,7 @@ impl Component for FetchServiceExample { // we want to redraw so that the page displays a 'fetching...' message to the user true } - Self::Message::ReceiveLocation(location) => { + ReceiveLocation(location) => { self.iss = location; self.fetching = false; // we want to redraw so that the page no longer says 'fetching...' From 43a6755a2e21860d9ce2284accc16c3c645aa3c5 Mon Sep 17 00:00:00 2001 From: Teymour Aldridge <42674621+teymour-aldridge@users.noreply.github.com> Date: Sat, 2 May 2020 14:49:36 +0100 Subject: [PATCH 10/16] Break out logic from `view` function. --- src/concepts/services/fetch.md | 46 +++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index 6d176aa..cd6fb66 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -37,6 +37,30 @@ struct FetchServiceExample { link: ComponentLink } +impl FetchServiceExample { + fn view_iss_location(&self) -> Html { + match self.iss { + Some(space_station) => html! { +

{"The ISS is at:"}

+

{format!("Latitude: {}", space_station.iss_location.latitude)}

+

{format!("Longitude: {}", space_station.iss_location.longitude)}

+ } + None => html! { + + } + } + } + fn is_fetching(&self) -> Html { + if self.fetching { + html! {

{"Fetching data..."}

} + } else { + html! {

} + } + } +} + #[derive(Deserialize, Debug, Clone)] struct ISSPosition { latitude: String, @@ -114,26 +138,8 @@ impl Component for FetchServiceExample { fn view(&self) -> Html { html! { <> - {if self.fetching { - html! {

{"Fetching data..."}

} - } else { - html! {

} - }} - { - match self.iss { - Some(space_station) => html! { -

{"The ISS is at:"}

-

{format!("Latitude: {}", space_station.iss_location.latitude)}

-

{format!("Longitude: {}", space_station.iss_location.longitude)}

- } - None => html! { - - } - } - } - + {self.is_fetching()} + {self.view_iss_location()} } } From 5f4d1305395dcc98c35fd2f2f7e4abba2aab8151 Mon Sep 17 00:00:00 2001 From: Teymour Aldridge <42674621+teymour-aldridge@users.noreply.github.com> Date: Sat, 2 May 2020 18:37:30 +0100 Subject: [PATCH 11/16] Update fetch.md --- src/concepts/services/fetch.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index cd6fb66..19996d5 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -107,15 +107,8 @@ impl Component for FetchServiceExample { let callback = self.link.callback(|response: Response>>| { // split up the response into the HTTP data about the request result and data from the request let (meta, Json(data)) = response.into_parts(); - if meta.status.is_success() { - match data.message { - "success" => { - Self::Message::ReceiveLocation(data.clone()) - } - _ => { - Self::Message::Noop - } - } + if meta.status.is_success() && data.message == "success" { + Self::Message::ReceiveLocation(data) } else { Self::Message::Noop } From aa5d5134b62a5e9bb028fc9ae3a2b7d086b707b8 Mon Sep 17 00:00:00 2001 From: Teymour Aldridge <42674621+teymour-aldridge@users.noreply.github.com> Date: Sat, 2 May 2020 21:15:17 +0100 Subject: [PATCH 12/16] Add missing `match` expression in example. --- src/concepts/services/fetch.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index 19996d5..49925fa 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -108,7 +108,11 @@ impl Component for FetchServiceExample { // split up the response into the HTTP data about the request result and data from the request let (meta, Json(data)) = response.into_parts(); if meta.status.is_success() && data.message == "success" { - Self::Message::ReceiveLocation(data) + Self::Message::ReceiveLocation(match data { + Ok(d) => d, + // handle errors more properly than this + Err(_) => panic!("Could not handle this error") + }) } else { Self::Message::Noop } @@ -116,7 +120,7 @@ impl Component for FetchServiceExample { // 3. pass the request and callback to the fetch service FetchService::new().fetch(request, callback); self.fetching = true; - // we want to redraw so that the page displays a 'fetching...' message to the user + // we want to redraw so that the page displays a 'fetching...' message to the user so return 'true' true } ReceiveLocation(location) => { From af9d7be82b7f33df89817ccd729d4c4c91f5e9c7 Mon Sep 17 00:00:00 2001 From: Teymour Aldridge Date: Fri, 8 May 2020 16:14:06 +0100 Subject: [PATCH 13/16] Fixed a type error. --- src/concepts/services/fetch.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index 49925fa..ebcc897 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -106,7 +106,8 @@ impl Component for FetchServiceExample { // 2. construct a callback let callback = self.link.callback(|response: Response>>| { // split up the response into the HTTP data about the request result and data from the request - let (meta, Json(data)) = response.into_parts(); + // Json(data) has type `Json>` + let (meta, Json(Ok(data))) = response.into_parts(); if meta.status.is_success() && data.message == "success" { Self::Message::ReceiveLocation(match data { Ok(d) => d, @@ -126,7 +127,7 @@ impl Component for FetchServiceExample { ReceiveLocation(location) => { self.iss = location; self.fetching = false; - // we want to redraw so that the page no longer says 'fetching...' + // we want to redraw so that the page displays the location of the ISS instead of 'fetching...' true } _ => false From 4aabb63576eb4549aba654b09dfbd46ef315d00a Mon Sep 17 00:00:00 2001 From: Teymour Aldridge Date: Tue, 23 Jun 2020 11:35:34 +0100 Subject: [PATCH 14/16] Add some error handling details. --- src/concepts/services/fetch.md | 44 +++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index ebcc897..4aa6946 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -8,21 +8,31 @@ Yew has a struct `Request` (which comes from the `http` crate) that is used to ' ```rust use yew::services::fetch::Request; use yew::format::Nothing; -let get_request = Request::get("https://example.com/api/v1/get/something").body(Nothing).expect("Could not build that request") +let get_request = Request::get("https://example.com/api/v1/get/something").body(Nothing).expect("Could not build that request"); ``` ```rust use yew::services::fetch::Request; use yew::format::Json; use serde_json::json; -let post_request = Request::post("https://example.com/api/v1/post/something").header("Content-Type", "application/json").body(Json(&json!({"key": "value"}))).expect("Could not build that request.") +let post_request = Request::post("https://example.com/api/v1/post/something").header("Content-Type", "application/json").body(Json(&json!({"key": "value"}))).expect("Could not build that request."); ``` ### Dispatching requests -The `FetchService` provides a binding to the browser's `fetch` API. Requests can be sent using either `FetchService::fetch` or `FetchService::fetch_with_options` (`fetch_with_options` should be used where cookies need to be sent in a request). +The `FetchService` provides a binding to the browser's `fetch` API. Requests can be sent using either +`FetchService::fetch` or `FetchService::fetch_with_options` (`fetch_with_options` should be used where cookies need to +be sent in a request). -`FetchService::fetch` accepts two parameters: a `Request` object and a `Callback`. The closure with which the callback is constructed must take a single parameter of type `Response`. `Response` accepts a type argument – the type must implement `From`. +`FetchService::fetch` accepts two parameters: a `Request` object and a `Callback`. The closure with which the callback +is constructed must take a single parameter of type `Response`. `Response` accepts a type argument – the type must +implement `From`. + +It's important that the `FetchTask` returned is kept alive until the request has finished – i.e. it should not be +dropped until the request has finsihed and a response has been obtained. If the `FetchTask` is dropped then the request +will be cancelled. {% hint style="info" %} -If you keep getting an error saying that "the operation was aborted" or "Error 408" this might be because the [CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) of the website you are trying to access are not set correctly. +If you keep getting an error saying that "the operation was aborted" or "Error 408" this might be because the +[CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) of the website you are trying to access are +not set correctly. {% endhint %} ```rust @@ -34,7 +44,8 @@ use serde::Deserialize; struct FetchServiceExample { ft: Option, iss: Option, - link: ComponentLink + link: ComponentLink, + error: Option } impl FetchServiceExample { @@ -79,7 +90,8 @@ struct ISS { enum Msg { GetLocation, Noop, - ReceiveLocation(ISS) + ReceiveLocation(ISS), + FetchError(String) } impl Component for FetchServiceExample { @@ -115,11 +127,11 @@ impl Component for FetchServiceExample { Err(_) => panic!("Could not handle this error") }) } else { - Self::Message::Noop + Self::Message::FetchError(data.message) } }); // 3. pass the request and callback to the fetch service - FetchService::new().fetch(request, callback); + FetchService::fetch(request, callback); self.fetching = true; // we want to redraw so that the page displays a 'fetching...' message to the user so return 'true' true @@ -130,6 +142,9 @@ impl Component for FetchServiceExample { // we want to redraw so that the page displays the location of the ISS instead of 'fetching...' true } + FetchError(error) => { + self.error = error; + } _ => false } } @@ -138,12 +153,23 @@ impl Component for FetchServiceExample { <> {self.is_fetching()} {self.view_iss_location()} + { + if let Some(error) = self.error { +

{error.clone()}

+ } + } } } } ``` +## Debugging the `FetchService` + +Most browser's developer tools have a "network" pane which can be used to inspect and view requests browsers have made, +including data such as request headers and the contents of responses. This can be a useful way to gain an insight into +what is happening. + ## Further reading * [The API documentation](https://docs.rs/yew/0.14.3/yew/services/fetch/index.html) * The [dashboard](https://github.com/yewstack/yew/tree/master/examples/dashboard) and [npm_and_rest](https://github.com/yewstack/yew/tree/master/examples/web_sys/npm_and_rest) examples. From 3419f7c2b72a1688bafcba390bd41674776bda57 Mon Sep 17 00:00:00 2001 From: Teymour Aldridge Date: Wed, 8 Jul 2020 11:09:34 +0100 Subject: [PATCH 15/16] Shorten line lengths (to ~100 characters max per line). --- src/concepts/services/fetch.md | 36 +++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index 4aa6946..c275b0f 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -1,10 +1,12 @@ # The Fetch Service ## Introduction -The fetch module can be used to make requests to a server. This allows a Yew application to connect to a backend and provide interactive functionality. +The fetch module can be used to make requests to a server. This allows a Yew application to connect +to a backend server and provide interactive functionality. ## Making requests ### Building requests -Yew has a struct `Request` (which comes from the `http` crate) that is used to 'build' requests before they can be dispatched to a server. The body type of the request must have the trait `Into`. +Yew has a struct `Request` (which comes from the `http` crate) that is used to 'build' requests +before they can be dispatched to a server. The body type of the request must have the trait `Into`. ```rust use yew::services::fetch::Request; use yew::format::Nothing; @@ -18,21 +20,22 @@ let post_request = Request::post("https://example.com/api/v1/post/something").he ``` ### Dispatching requests The `FetchService` provides a binding to the browser's `fetch` API. Requests can be sent using either -`FetchService::fetch` or `FetchService::fetch_with_options` (`fetch_with_options` should be used where cookies need to +`FetchService::fetch` or `FetchService::fetch_with_options` (`fetch_with_options` should be used +where cookies need to be sent in a request). -`FetchService::fetch` accepts two parameters: a `Request` object and a `Callback`. The closure with which the callback -is constructed must take a single parameter of type `Response`. `Response` accepts a type argument – the type must -implement `From`. +`FetchService::fetch` accepts two parameters: a `Request` object and a `Callback`. The closure with +which the callback is constructed must take a single parameter of type `Response`. `Response` accepts +a type argument – the type must implement `From`. -It's important that the `FetchTask` returned is kept alive until the request has finished – i.e. it should not be -dropped until the request has finsihed and a response has been obtained. If the `FetchTask` is dropped then the request -will be cancelled. +It's important that the `FetchTask` returned is kept alive until the request has finished – i.e. it +should not be dropped until the request has finsihed and a response has been obtained. If the +`FetchTask` is dropped then the request will be cancelled. {% hint style="info" %} -If you keep getting an error saying that "the operation was aborted" or "Error 408" this might be because the -[CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) of the website you are trying to access are -not set correctly. +If you keep getting an error saying that "the operation was aborted" or "Error 408" this might be +because the [CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) of the website +you are trying to access are not set correctly. {% endhint %} ```rust @@ -166,10 +169,11 @@ impl Component for FetchServiceExample { ## Debugging the `FetchService` -Most browser's developer tools have a "network" pane which can be used to inspect and view requests browsers have made, -including data such as request headers and the contents of responses. This can be a useful way to gain an insight into -what is happening. +Most browsers' developer tools have a "network" pane which can be used to inspect and view requests +browsers have made, including data such as request headers and the contents of responses. This can be +a useful way to gain an insight into what is happening. ## Further reading * [The API documentation](https://docs.rs/yew/0.14.3/yew/services/fetch/index.html) -* The [dashboard](https://github.com/yewstack/yew/tree/master/examples/dashboard) and [npm_and_rest](https://github.com/yewstack/yew/tree/master/examples/web_sys/npm_and_rest) examples. +* The [dashboard](https://github.com/yewstack/yew/tree/master/examples/dashboard) and +[npm_and_rest](https://github.com/yewstack/yew/tree/master/examples/web_sys/npm_and_rest) examples. From 8c42997eea2fccf483f0e8c0aa6312daeb0c2792 Mon Sep 17 00:00:00 2001 From: Teymour Aldridge Date: Wed, 8 Jul 2020 11:11:11 +0100 Subject: [PATCH 16/16] Make a sentence more detailed. --- src/concepts/services/fetch.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/concepts/services/fetch.md b/src/concepts/services/fetch.md index c275b0f..343a985 100644 --- a/src/concepts/services/fetch.md +++ b/src/concepts/services/fetch.md @@ -171,7 +171,8 @@ impl Component for FetchServiceExample { Most browsers' developer tools have a "network" pane which can be used to inspect and view requests browsers have made, including data such as request headers and the contents of responses. This can be -a useful way to gain an insight into what is happening. +a useful way to gain an insight into what requests are being made, the data being sent to the server +as well as the return data from the server. ## Further reading * [The API documentation](https://docs.rs/yew/0.14.3/yew/services/fetch/index.html)