router_restore_scroll.rs 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. use std::rc::Rc;
  2. use dioxus::html::geometry::PixelsVector2D;
  3. use dioxus::prelude::*;
  4. #[derive(Clone, Routable, Debug, PartialEq)]
  5. enum Route {
  6. #[route("/")]
  7. Home {},
  8. #[route("/blog/:id")]
  9. Blog { id: i32 },
  10. }
  11. fn main() {
  12. dioxus::launch(App);
  13. }
  14. #[component]
  15. fn App() -> Element {
  16. use_context_provider(|| Signal::new(Scroll::default()));
  17. rsx! {
  18. Router::<Route> {}
  19. }
  20. }
  21. #[component]
  22. fn Blog(id: i32) -> Element {
  23. rsx! {
  24. GoBackButton { "Go back" }
  25. div { "Blog post {id}" }
  26. }
  27. }
  28. type Scroll = Option<PixelsVector2D>;
  29. #[component]
  30. fn Home() -> Element {
  31. let mut element: Signal<Option<Rc<MountedData>>> = use_signal(|| None);
  32. let mut scroll = use_context::<Signal<Scroll>>();
  33. _ = use_resource(move || async move {
  34. if let (Some(element), Some(scroll)) = (element.read().as_ref(), *scroll.peek()) {
  35. element
  36. .scroll(scroll, ScrollBehavior::Instant)
  37. .await
  38. .unwrap();
  39. }
  40. });
  41. rsx! {
  42. div {
  43. height: "300px",
  44. overflow_y: "auto",
  45. border: "1px solid black",
  46. onmounted: move |event| element.set(Some(event.data())),
  47. onscroll: move |_| async move {
  48. if let Some(element) = element.cloned() {
  49. scroll.set(Some(element.get_scroll_offset().await.unwrap()))
  50. }
  51. },
  52. for i in 0..100 {
  53. div { height: "20px",
  54. Link { to: Route::Blog { id: i }, "Blog {i}" }
  55. }
  56. }
  57. }
  58. }
  59. }