This is unreleased documentation for Yew Next version.
For up-to-date documentation, see the latest version on docs.rs.

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}