suspense.rs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #![allow(non_snake_case)]
  2. //! Suspense in Dioxus
  3. //!
  4. //! Currently, `rsx!` does not accept futures as values. To achieve the functionality
  5. //! of suspense, we need to make a new component that performs its own suspense
  6. //! handling.
  7. //!
  8. //! In this example, we render the `Doggo` component which starts a future that
  9. //! will cause it to fetch a random dog image from the Dog API. Since the data
  10. //! is not ready immediately, we render some loading text.
  11. //!
  12. //! We can achieve the majority of suspense functionality by composing "suspenseful"
  13. //! primitives in our own custom components.
  14. use dioxus::prelude::*;
  15. use dioxus_desktop::{Config, LogicalSize, WindowBuilder};
  16. fn main() {
  17. Config::new()
  18. .with_window(
  19. WindowBuilder::new()
  20. .with_title("Doggo Fetcher")
  21. .with_inner_size(LogicalSize::new(600.0, 800.0)),
  22. )
  23. .launch(app)
  24. }
  25. fn app() -> Element {
  26. rsx! {
  27. div {
  28. h1 {"Dogs are very important"}
  29. p {
  30. "The dog or domestic dog (Canis familiaris[4][5] or Canis lupus familiaris[5])"
  31. "is a domesticated descendant of the wolf which is characterized by an upturning tail."
  32. "The dog derived from an ancient, extinct wolf,[6][7] and the modern grey wolf is the"
  33. "dog's nearest living relative.[8] The dog was the first species to be domesticated,[9][8]"
  34. "by hunter–gatherers over 15,000 years ago,[7] before the development of agriculture.[1]"
  35. }
  36. h3 { "Illustrious Dog Photo" }
  37. Doggo { }
  38. }
  39. }
  40. }
  41. /// This component will re-render when the future has finished
  42. /// Suspense is achieved my moving the future into only the component that
  43. /// actually renders the data.
  44. fn Doggo() -> Element {
  45. let fut = use_future(|| async move {
  46. #[derive(serde::Deserialize)]
  47. struct DogApi {
  48. message: String,
  49. }
  50. reqwest::get("https://dog.ceo/api/breeds/image/random/")
  51. .await
  52. .unwrap()
  53. .json::<DogApi>()
  54. .await
  55. });
  56. match fut.value().read().as_ref() {
  57. Some(Ok(resp)) => rsx! {
  58. button {
  59. onclick: move |_| fut.restart(),
  60. "Click to fetch another doggo"
  61. }
  62. div {
  63. img {
  64. max_width: "500px",
  65. max_height: "500px",
  66. src: "{resp.message}",
  67. }
  68. }
  69. },
  70. Some(Err(_)) => rsx! { div { "loading dogs failed" } },
  71. None => rsx! { div { "loading dogs..." } },
  72. }
  73. }