task.rs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. //! Example: Tasks
  2. //! --------------
  3. //!
  4. //! Built around the same system that powers suspense, Dioxus also allows users to write arbitrary tasks that can modify
  5. //! state asynchronously. `use_task` takes a future and returns a task handle and an option that holds the tasks's return
  6. //! value. When the task completes, the component will re-render with the result freshly available.
  7. //!
  8. //! Tasks don't necessarily need to complete, however. It would be completely reasonable to wire up a websocket receiver
  9. //! in a task and have it work infinitely while the app is running. If the socket throws an error, the task could complete
  10. //! and the UI could present a helpful error message.
  11. //!
  12. //! Tasks also return the `TaskHandle` type which lets other component logic start, stop, and restart the task at any time.
  13. //! Tasks are very much like an async-flavoroued coroutine, making them incredibly powerful.
  14. //!
  15. //! Tasks must be valid for the 'static lifetime, so any state management neeeds to be cloned into the closure. `use_state`
  16. //! has a method called `for_async` which generates an AsyncUseState wrapper. This has a very similar API to the regualr
  17. //! `use_state` but is `static.
  18. //!
  19. //! Remeber `use_task` is a hook! Don't call it out of order or in loops. You might aaccidentally swap the task handles
  20. //! and break things in subtle ways.
  21. //!
  22. //! Whenever a component is scheduled for deletion, the task is dropped. Make sure that whatever primitives used in the
  23. //! task have a valid drop implementation and won't leave resources tied up.
  24. use dioxus::prelude::*;
  25. pub static Example: Component = |cx| {
  26. let count = use_state(&cx, || 0);
  27. let mut direction = use_state(&cx, || 1);
  28. // Tasks are 'static, so we need to copy relevant items in
  29. let (async_count, dir) = (count.for_async(), *direction);
  30. let (task, result) = use_task(cx, move || async move {
  31. loop {
  32. gloo_timers::future::TimeoutFuture::new(250).await;
  33. *async_count.get_mut() += dir;
  34. }
  35. });
  36. cx.render(rsx! {
  37. div {
  38. h1 {"count is {count}"}
  39. button {
  40. onclick: move |_| task.stop(),
  41. "Stop counting"
  42. }
  43. button {
  44. onclick: move |_| task.resume(),
  45. "Start counting"
  46. }
  47. button {
  48. onclick: move |_| {
  49. direction *= -1;
  50. task.restart();
  51. }
  52. "Switch counting direcion"
  53. }
  54. }
  55. })
  56. };