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}