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: FC<()> = |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. // Count infinitely!
  32. loop {
  33. gloo_timers::future::TimeoutFuture::new(250).await;
  34. *async_count.get_mut() += dir;
  35. }
  36. });
  37. cx.render(rsx! {
  38. div {
  39. h1 {"count is {count}"}
  40. button {
  41. "Stop counting"
  42. onclick: move |_| task.stop()
  43. }
  44. button {
  45. "Start counting"
  46. onclick: move |_| task.start()
  47. }
  48. button {
  49. "Switch counting direcion"
  50. onclick: move |_| {
  51. direction *= -1;
  52. task.restart();
  53. }
  54. }
  55. }
  56. })
  57. };