dioxus_core/
fragment.rs

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