borrowed.rs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #![allow(non_snake_case)]
  2. //! Example: Extremely nested borrowing
  3. //! -----------------------------------
  4. //!
  5. //! Dioxus manages borrow lifetimes for you. This means any child may borrow from its parent. However, it is not possible
  6. //! to hand out an &mut T to children - all props are consumed by &P, so you'd only get an &&mut T.
  7. //!
  8. //! How does it work?
  9. //!
  10. //! Dioxus will manually drop closures and props - things that borrow data before the component is ran again. This is done
  11. //! "bottom up" from the lowest child all the way to the initiating parent. As it traverses each listener and prop, the
  12. //! drop implementation is manually called, freeing any memory and ensuring that memory is not leaked.
  13. //!
  14. //! We cannot drop from the parent to the children - if the drop implementation modifies the data, downstream references
  15. //! might be broken since we take an &mut T and and &T to the data. Instead, we work bottom up, making sure to remove any
  16. //! potential references to the data before finally giving out an &mut T. This prevents us from mutably aliasing the data,
  17. //! and is proven to be safe with MIRI.
  18. use dioxus::prelude::*;
  19. fn main() {
  20. dioxus::desktop::launch(App, |c| c);
  21. }
  22. fn App<'a>(cx: Context<'a>, props: &()) -> DomTree<'a> {
  23. let text: &'a mut Vec<String> = cx.use_hook(|_| vec![String::from("abc=def")], |f| f, |_| {});
  24. let first = text.get_mut(0).unwrap();
  25. cx.render(rsx! {
  26. div {
  27. Child1 {
  28. text: first
  29. }
  30. }
  31. })
  32. }
  33. #[derive(Props)]
  34. struct C1Props<'a> {
  35. text: &'a mut String,
  36. }
  37. impl<'a> Drop for C1Props<'a> {
  38. fn drop(&mut self) {}
  39. }
  40. fn Child1<'a>(cx: Context<'a>, props: &'a C1Props) -> DomTree<'a> {
  41. let (left, right) = props.text.split_once("=").unwrap();
  42. cx.render(rsx! {
  43. div {
  44. Child2 { text: left }
  45. Child2 { text: right }
  46. }
  47. })
  48. }
  49. #[derive(Props)]
  50. struct C2Props<'a> {
  51. text: &'a str,
  52. }
  53. impl<'a> Drop for C2Props<'a> {
  54. fn drop(&mut self) {
  55. todo!()
  56. }
  57. }
  58. fn Child2<'a>(cx: Context<'a>, props: &'a C2Props) -> DomTree<'a> {
  59. cx.render(rsx! {
  60. Child3 {
  61. text: props.text
  62. }
  63. })
  64. }
  65. #[derive(Props)]
  66. struct C3Props<'a> {
  67. text: &'a str,
  68. }
  69. fn Child3<'a>(cx: Context<'a>, props: &C3Props) -> DomTree<'a> {
  70. cx.render(rsx! {
  71. div { "{props.text}"}
  72. })
  73. }