fragment.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. use crate::innerlude::*;
  2. /// Create inline fragments using Component syntax.
  3. ///
  4. /// ## Details
  5. ///
  6. /// Fragments capture a series of children without rendering extra nodes.
  7. ///
  8. /// Creating fragments explicitly with the Fragment component is particularly useful when rendering lists or tables and
  9. /// a key is needed to identify each item.
  10. ///
  11. /// ## Example
  12. ///
  13. /// ```rust, ignore
  14. /// rsx!{
  15. /// Fragment { key: "abc" }
  16. /// }
  17. /// ```
  18. ///
  19. /// ## Usage
  20. ///
  21. /// Fragments are incredibly useful when necessary, but *do* add cost in the diffing phase.
  22. /// Try to avoid highly nested fragments if you can. Unlike React, there is no protection against infinitely nested fragments.
  23. ///
  24. /// This function defines a dedicated `Fragment` component that can be used to create inline fragments in the RSX macro.
  25. ///
  26. /// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it.
  27. #[allow(non_upper_case_globals, non_snake_case)]
  28. pub fn Fragment(cx: FragmentProps) -> Element {
  29. cx.0
  30. }
  31. #[derive(Clone, PartialEq)]
  32. pub struct FragmentProps(Element);
  33. pub struct FragmentBuilder<const BUILT: bool>(Element);
  34. impl FragmentBuilder<false> {
  35. pub fn children(self, children: Element) -> FragmentBuilder<true> {
  36. FragmentBuilder(children)
  37. }
  38. }
  39. impl<const A: bool> FragmentBuilder<A> {
  40. pub fn build(self) -> FragmentProps {
  41. FragmentProps(self.0)
  42. }
  43. }
  44. /// Access the children elements passed into the component
  45. ///
  46. /// This enables patterns where a component is passed children from its parent.
  47. ///
  48. /// ## Details
  49. ///
  50. /// Unlike React, Dioxus allows *only* lists of children to be passed from parent to child - not arbitrary functions
  51. /// or classes. If you want to generate nodes instead of accepting them as a list, consider declaring a closure
  52. /// on the props that takes Context.
  53. ///
  54. /// If a parent passes children into a component, the child will always re-render when the parent re-renders. In other
  55. /// words, a component cannot be automatically memoized if it borrows nodes from its parent, even if the component's
  56. /// props are valid for the static lifetime.
  57. ///
  58. /// ## Example
  59. ///
  60. /// ```rust, ignore
  61. /// fn app() -> Element {
  62. /// rsx!{
  63. /// CustomCard {
  64. /// h1 {}
  65. /// p {}
  66. /// }
  67. /// })
  68. /// }
  69. ///
  70. /// #[derive(PartialEq, Props)]
  71. /// struct CardProps {
  72. /// children: Element
  73. /// }
  74. ///
  75. /// fn CustomCard(cx: CardProps) -> Element {
  76. /// rsx!{
  77. /// div {
  78. /// h1 {"Title card"}
  79. /// {cx.children}
  80. /// }
  81. /// })
  82. /// }
  83. /// ```
  84. impl Properties for FragmentProps {
  85. type Builder = FragmentBuilder<false>;
  86. fn builder() -> Self::Builder {
  87. FragmentBuilder(None)
  88. }
  89. fn memoize(&mut self, new: &Self) -> bool {
  90. let equal = self == new;
  91. if !equal {
  92. let new_clone = new.clone();
  93. self.0 = new_clone.0;
  94. }
  95. equal
  96. }
  97. }