diff_component.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. use dioxus::dioxus_core::{ElementId, Mutation::*};
  2. use dioxus::prelude::*;
  3. use pretty_assertions::assert_eq;
  4. /// When returning sets of components, we do a light diff of the contents to preserve some react-like functionality
  5. ///
  6. /// This means that nav_bar should never get re-created and that we should only be swapping out
  7. /// different pointers
  8. #[test]
  9. fn component_swap() {
  10. // Check that templates with the same structure are deduplicated at compile time
  11. // If they are not, this test will fail because it is being run in debug mode where templates are not deduped
  12. let dynamic = 0;
  13. let template_1 = rsx! { "{dynamic}" };
  14. let template_2 = rsx! { "{dynamic}" };
  15. if template_1.unwrap().template != template_2.unwrap().template {
  16. return;
  17. }
  18. fn app() -> Element {
  19. let mut render_phase = use_signal(|| 0);
  20. render_phase += 1;
  21. match render_phase() {
  22. 0 => rsx! {
  23. nav_bar {}
  24. dash_board {}
  25. },
  26. 1 => rsx! {
  27. nav_bar {}
  28. dash_results {}
  29. },
  30. 2 => rsx! {
  31. nav_bar {}
  32. dash_board {}
  33. },
  34. 3 => rsx! {
  35. nav_bar {}
  36. dash_results {}
  37. },
  38. 4 => rsx! {
  39. nav_bar {}
  40. dash_board {}
  41. },
  42. _ => rsx!("blah"),
  43. }
  44. }
  45. fn nav_bar() -> Element {
  46. rsx! {
  47. h1 {
  48. "NavBar"
  49. for _ in 0..3 {
  50. nav_link {}
  51. }
  52. }
  53. }
  54. }
  55. fn nav_link() -> Element {
  56. rsx!( h1 { "nav_link" } )
  57. }
  58. fn dash_board() -> Element {
  59. rsx!( div { "dashboard" } )
  60. }
  61. fn dash_results() -> Element {
  62. rsx!( div { "results" } )
  63. }
  64. let mut dom = VirtualDom::new(app);
  65. {
  66. let edits = dom.rebuild_to_vec();
  67. assert_eq!(
  68. edits.edits,
  69. [
  70. LoadTemplate { index: 0, id: ElementId(1) },
  71. LoadTemplate { index: 0, id: ElementId(2) },
  72. LoadTemplate { index: 0, id: ElementId(3) },
  73. LoadTemplate { index: 0, id: ElementId(4) },
  74. ReplacePlaceholder { path: &[1], m: 3 },
  75. LoadTemplate { index: 0, id: ElementId(5) },
  76. AppendChildren { m: 2, id: ElementId(0) }
  77. ]
  78. );
  79. }
  80. dom.mark_dirty(ScopeId::APP);
  81. assert_eq!(
  82. dom.render_immediate_to_vec().edits,
  83. [
  84. LoadTemplate { index: 0, id: ElementId(6) },
  85. ReplaceWith { id: ElementId(5), m: 1 }
  86. ]
  87. );
  88. dom.mark_dirty(ScopeId::APP);
  89. assert_eq!(
  90. dom.render_immediate_to_vec().edits,
  91. [
  92. LoadTemplate { index: 0, id: ElementId(5) },
  93. ReplaceWith { id: ElementId(6), m: 1 }
  94. ]
  95. );
  96. dom.mark_dirty(ScopeId::APP);
  97. assert_eq!(
  98. dom.render_immediate_to_vec().edits,
  99. [
  100. LoadTemplate { index: 0, id: ElementId(6) },
  101. ReplaceWith { id: ElementId(5), m: 1 }
  102. ]
  103. );
  104. }