From d803df933663da70e705d476fe2cb7d5350fcbb7 Mon Sep 17 00:00:00 2001 From: Kaede Hoshikawa Date: Sat, 5 Aug 2023 22:33:23 +0900 Subject: [PATCH] Update documentation around Children (#3297) * Update Children to use Html. * Fix website. * Update website/docs/advanced-topics/children.mdx * add further reading section --------- Co-authored-by: Muhammad Hamza --- website/docs/advanced-topics/children.mdx | 69 ++++++++++++++++++- website/docs/advanced-topics/portals.mdx | 4 +- website/docs/concepts/contexts.mdx | 4 +- .../concepts/function-components/children.mdx | 10 +-- website/docs/concepts/html/classes.mdx | 2 +- website/docs/concepts/html/components.mdx | 53 +------------- 6 files changed, 77 insertions(+), 65 deletions(-) diff --git a/website/docs/advanced-topics/children.mdx b/website/docs/advanced-topics/children.mdx index a05dbf4b506..80dae96ef3a 100644 --- a/website/docs/advanced-topics/children.mdx +++ b/website/docs/advanced-topics/children.mdx @@ -2,6 +2,18 @@ title: 'Children' --- +:::caution + +Inspecting and manipulating `Children` can often result in surprising and hard-to-explain behaviours in your application. +This can lead to edge cases and often does not yield expected result. +You should consider other approaches if you are trying to manipulate `Children`. + +Yew supports using `Html` as the type of the children prop. +You should use `Html` as children if you do not need `Children` or `ChildrenRenderer`. +It doesn't have the drawbacks of `Children` and has a lower performance overhead. + +::: + ## General usage _Most of the time,_ when allowing a component to have children, you don't care @@ -9,12 +21,12 @@ what type of children the component has. In such cases, the below example will suffice. ```rust -use yew::{html, Children, Component, Context, Html, Properties}; +use yew::{html, Component, Context, Html, Properties}; #[derive(Properties, PartialEq)] pub struct ListProps { #[prop_or_default] - pub children: Children, + pub children: Html, } pub struct List; @@ -30,7 +42,7 @@ impl Component for List { fn view(&self, ctx: &Context) -> Html { html! {
- { for ctx.props().children.iter() } + {ctx.props().children.clone()}
} } @@ -90,6 +102,53 @@ impl Component for List { } ``` +## Nested Children with Props + +Nested component properties can be accessed and mutated if the containing component types its children. + +```rust +use std::rc::Rc; +use yew::prelude::*; + +#[derive(Clone, PartialEq, Properties)] +pub struct ListItemProps { + value: String, +} + +#[function_component] +fn ListItem(props: &ListItemProps) -> Html { + let ListItemProps { value } = props.clone(); + html! { + + {value} + + } +} + +#[derive(PartialEq, Properties)] +pub struct Props { + pub children: ChildrenWithProps, +} + +#[function_component] +fn List(props: &Props) -> Html { + let modified_children = props.children.iter().map(|mut item| { + let mut props = Rc::make_mut(&mut item.props); + props.value = format!("item-{}", props.value); + item + }); + html! { for modified_children } +} + +html! { + + + + + +}; +``` + ### Enum typed children Of course, sometimes you might need to restrict the children to a few different @@ -253,3 +312,7 @@ pub fn render_page(with_sidebar: bool) -> Html { } } ``` + +## Further Reading + +- For a real-world example of this pattern, check out the yew-router source code. For a more advanced example, check out the [nested-list example](https://github.com/yewstack/yew/tree/master/examples/nested_list) in the main yew repository. diff --git a/website/docs/advanced-topics/portals.mdx b/website/docs/advanced-topics/portals.mdx index 3a5d1de28bd..9fd76fb37f0 100644 --- a/website/docs/advanced-topics/portals.mdx +++ b/website/docs/advanced-topics/portals.mdx @@ -28,7 +28,7 @@ use yew::prelude::*; #[derive(Properties, PartialEq)] pub struct ModalProps { #[prop_or_default] - pub children: Children, + pub children: Html, } #[function_component] @@ -38,7 +38,7 @@ fn Modal(props: &ModalProps) -> Html { .expect("Expected to find a #modal_host element"); create_portal( - html!{ {for props.children.iter()} }, + props.children.clone(), modal_host.into(), ) } diff --git a/website/docs/concepts/contexts.mdx b/website/docs/concepts/contexts.mdx index 7489747f822..230f8daa6c4 100644 --- a/website/docs/concepts/contexts.mdx +++ b/website/docs/concepts/contexts.mdx @@ -21,7 +21,7 @@ This situation is called "Prop Drilling". Consider the following example which passes down the theme using props: ```rust -use yew::{html, Children, Component, Context, Html, Properties, function_component}; +use yew::{html, Component, Context, Html, Properties, function_component}; #[derive(Clone, PartialEq)] pub struct Theme { @@ -51,7 +51,7 @@ fn Navbar(props: &NavbarProps) -> Html { #[derive(PartialEq, Properties)] pub struct ThemeProps { theme: Theme, - children: Children, + children: Html, } #[function_component] diff --git a/website/docs/concepts/function-components/children.mdx b/website/docs/concepts/function-components/children.mdx index 5acafbf0b29..cbb6ffdda41 100644 --- a/website/docs/concepts/function-components/children.mdx +++ b/website/docs/concepts/function-components/children.mdx @@ -5,7 +5,7 @@ title: 'Children' `Children` is a special prop type that allows you to receive nested `Html` that is provided like html child elements. ```rust -use yew::{function_component, html, Html, Properties, Children}; +use yew::{function_component, html, Html, Properties}; #[function_component] fn App() -> Html { @@ -22,7 +22,7 @@ fn App() -> Html { #[derive(Properties, PartialEq)] pub struct Props { // highlight-next-line - pub children: Children, // the field name `children` is important! + pub children: Html, // the field name `children` is important! } #[function_component] @@ -30,12 +30,8 @@ fn HelloWorld(props: &Props) -> Html { html! {
// highlight-next-line - { for props.children.iter() } // you can forward children like this + { props.children.clone() } // you can forward children like this
} } ``` - -## Further reading - -- [Advanced ways to handle children](../../advanced-topics/children) diff --git a/website/docs/concepts/html/classes.mdx b/website/docs/concepts/html/classes.mdx index a2b823ddb45..5cd87106813 100644 --- a/website/docs/concepts/html/classes.mdx +++ b/website/docs/concepts/html/classes.mdx @@ -104,7 +104,7 @@ struct Props { #[prop_or_default] class: Classes, fill: bool, - children: Children, + children: Html, } #[function_component] diff --git a/website/docs/concepts/html/components.mdx b/website/docs/concepts/html/components.mdx index 81cf19a0dae..bc1b00aa24d 100644 --- a/website/docs/concepts/html/components.mdx +++ b/website/docs/concepts/html/components.mdx @@ -63,7 +63,7 @@ use yew::prelude::*; #[derive(PartialEq, Properties)] struct Props { id: String, - children: Children, + children: Html, } #[function_component] @@ -94,7 +94,7 @@ use yew::prelude::*; #[derive(PartialEq, Properties)] struct Props { id: String, - children: Children, + children: Html, } #[function_component] @@ -108,7 +108,7 @@ fn Container(props: &Props) -> Html { let props = yew::props!(Props { id: "container-2", - children: Children::default(), + children: Html::default(), }); html! { @@ -119,53 +119,6 @@ html! { }; ``` -## Nested Children with Props - -Nested component properties can be accessed and mutated if the containing component types its children. In the following example, the `List` component can wrap `ListItem` components. For a real-world example of this pattern, check out the `yew-router` source code. For a more advanced example, check out the `nested-list` example in the main yew repository. - -```rust -use std::rc::Rc; -use yew::prelude::*; - -#[derive(Clone, PartialEq, Properties)] -pub struct ListItemProps { - value: String, -} - -#[function_component] -fn ListItem(props: &ListItemProps) -> Html { - let ListItemProps { value } = props.clone(); - html! { - - {value} - - } -} - -#[derive(PartialEq, Properties)] -pub struct Props { - pub children: ChildrenWithProps, -} - -#[function_component] -fn List(props: &Props) -> Html { - let modified_children = props.children.iter().map(|mut item| { - let mut props = Rc::make_mut(&mut item.props); - props.value = format!("item-{}", props.value); - item - }); - html! { for modified_children } -} - -html! { - - - - - -}; -``` - ## Relevant examples - [Function Todo MVC](https://github.com/yewstack/yew/tree/master/examples/function_todomvc)