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