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 <muhammadhamza1311@gmail.com>
This commit is contained in:
Kaede Hoshikawa 2023-08-05 22:33:23 +09:00 committed by GitHub
parent 4daa2ecc8a
commit d803df9336
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 77 additions and 65 deletions

View File

@ -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<Self>) -> Html {
html! {
<div class="list">
{ for ctx.props().children.iter() }
{ctx.props().children.clone()}
</div>
}
}
@ -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! {
<span>
{value}
</span>
}
}
#[derive(PartialEq, Properties)]
pub struct Props {
pub children: ChildrenWithProps<ListItem>,
}
#[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! {
<List>
<ListItem value="a" />
<ListItem value="b" />
<ListItem value="c" />
</List>
};
```
### 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.

View File

@ -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(),
)
}

View File

@ -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]

View File

@ -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! {
<div class="very-stylized-container">
// highlight-next-line
{ for props.children.iter() } // you can forward children like this
{ props.children.clone() } // you can forward children like this
</div>
}
}
```
## Further reading
- [Advanced ways to handle children](../../advanced-topics/children)

View File

@ -104,7 +104,7 @@ struct Props {
#[prop_or_default]
class: Classes,
fill: bool,
children: Children,
children: Html,
}
#[function_component]

View File

@ -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! {
<span>
{value}
</span>
}
}
#[derive(PartialEq, Properties)]
pub struct Props {
pub children: ChildrenWithProps<ListItem>,
}
#[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! {
<List>
<ListItem value="a" />
<ListItem value="b" />
<ListItem value="c" />
</List>
};
```
## Relevant examples
- [Function Todo MVC](https://github.com/yewstack/yew/tree/master/examples/function_todomvc)