yew/html/component/marker.rs
1//! Primitive Components & Properties Types
2
3use crate::function_component;
4use crate::html::{BaseComponent, ChildrenProps, Html};
5
6/// A Component to represent a component that does not exist in current implementation.
7///
8/// During Hydration, Yew expected the Virtual DOM hierarchy to match the layout used in
9/// server-side rendering. However, sometimes it is possible / reasonable to omit certain components
10/// from one side of the implementation. This component is used to represent a component as if a
11/// component "existed" in the place it is defined.
12///
13/// # Warning
14///
15/// The Real DOM hierarchy must also match the server-side rendered artifact. This component is
16/// only usable when the original component does not introduce any additional elements. (e.g.:
17/// Context Providers)
18///
19/// A generic parameter is provided to help identify the component to be substituted.
20/// The type of the generic parameter is not required to be the same component that was in the other
21/// implementation. However, this behaviour may change in the future if more debug assertions were
22/// to be introduced. It is recommended that the generic parameter represents the component in the
23/// other implementation.
24///
25/// # Example
26///
27/// ```
28/// use yew::prelude::*;
29/// # use yew::html::ChildrenProps;
30/// #
31/// # #[function_component]
32/// # fn Comp(props: &ChildrenProps) -> Html {
33/// # Html::default()
34/// # }
35/// #
36/// # #[function_component]
37/// # fn Provider(props: &ChildrenProps) -> Html {
38/// # let children = props.children.clone();
39/// #
40/// # html! { <>{children}</> }
41/// # }
42/// # type Provider1 = Provider;
43/// # type Provider2 = Provider;
44/// # type Provider3 = Provider;
45/// # type Provider4 = Provider;
46///
47/// #[function_component]
48/// fn ServerApp() -> Html {
49/// // The Server Side Rendering Application has 3 Providers.
50/// html! {
51/// <Provider1>
52/// <Provider2>
53/// <Provider3>
54/// <Comp />
55/// </Provider3>
56/// </Provider2>
57/// </Provider1>
58/// }
59/// }
60///
61/// #[function_component]
62/// fn App() -> Html {
63/// // The Client Side Rendering Application has 4 Providers.
64/// html! {
65/// <Provider1>
66/// <Provider2>
67/// <Provider3>
68///
69/// // This provider does not exist on the server-side
70/// // Hydration will fail due to Virtual DOM layout mismatch.
71/// <Provider4>
72/// <Comp />
73/// </Provider4>
74///
75/// </Provider3>
76/// </Provider2>
77/// </Provider1>
78/// }
79/// }
80/// ```
81///
82/// To mitigate this, we can use a `PhantomComponent`:
83///
84/// ```
85/// use yew::prelude::*;
86/// # use yew::html::{PhantomComponent, ChildrenProps};
87/// #
88/// # #[function_component]
89/// # fn Comp(props: &ChildrenProps) -> Html {
90/// # Html::default()
91/// # }
92/// #
93/// # #[function_component]
94/// # fn Provider(props: &ChildrenProps) -> Html {
95/// # let children = props.children.clone();
96/// #
97/// # html! { <>{children}</> }
98/// # }
99/// # type Provider1 = Provider;
100/// # type Provider2 = Provider;
101/// # type Provider3 = Provider;
102/// # type Provider4 = Provider;
103///
104/// #[function_component]
105/// fn ServerApp() -> Html {
106/// html! {
107/// <Provider1>
108/// <Provider2>
109/// <Provider3>
110/// // We add a PhantomComponent for Provider4,
111/// // it acts if a Provider4 component presents in this position.
112/// <PhantomComponent<Provider4>>
113/// <Comp />
114/// </PhantomComponent<Provider4>>
115/// </Provider3>
116/// </Provider2>
117/// </Provider1>
118/// }
119/// }
120///
121/// #[function_component]
122/// fn App() -> Html {
123/// html! {
124/// <Provider1>
125/// <Provider2>
126/// <Provider3>
127///
128/// // Hydration will succeed as the PhantomComponent in the server-side
129/// // implementation will represent a Provider4 component in this position.
130/// <Provider4>
131/// <Comp />
132/// </Provider4>
133///
134/// </Provider3>
135/// </Provider2>
136/// </Provider1>
137/// }
138/// }
139/// ```
140#[function_component]
141pub fn PhantomComponent<T>(props: &ChildrenProps) -> Html
142where
143 T: BaseComponent,
144{
145 props.children.clone()
146}