mirror of https://github.com/yewstack/yew
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:
parent
4daa2ecc8a
commit
d803df9336
|
@ -2,6 +2,18 @@
|
||||||
title: 'Children'
|
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
|
## General usage
|
||||||
|
|
||||||
_Most of the time,_ when allowing a component to have children, you don't care
|
_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.
|
suffice.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use yew::{html, Children, Component, Context, Html, Properties};
|
use yew::{html, Component, Context, Html, Properties};
|
||||||
|
|
||||||
#[derive(Properties, PartialEq)]
|
#[derive(Properties, PartialEq)]
|
||||||
pub struct ListProps {
|
pub struct ListProps {
|
||||||
#[prop_or_default]
|
#[prop_or_default]
|
||||||
pub children: Children,
|
pub children: Html,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct List;
|
pub struct List;
|
||||||
|
@ -30,7 +42,7 @@ impl Component for List {
|
||||||
fn view(&self, ctx: &Context<Self>) -> Html {
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
||||||
html! {
|
html! {
|
||||||
<div class="list">
|
<div class="list">
|
||||||
{ for ctx.props().children.iter() }
|
{ctx.props().children.clone()}
|
||||||
</div>
|
</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
|
### Enum typed children
|
||||||
|
|
||||||
Of course, sometimes you might need to restrict the children to a few different
|
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.
|
||||||
|
|
|
@ -28,7 +28,7 @@ use yew::prelude::*;
|
||||||
#[derive(Properties, PartialEq)]
|
#[derive(Properties, PartialEq)]
|
||||||
pub struct ModalProps {
|
pub struct ModalProps {
|
||||||
#[prop_or_default]
|
#[prop_or_default]
|
||||||
pub children: Children,
|
pub children: Html,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[function_component]
|
#[function_component]
|
||||||
|
@ -38,7 +38,7 @@ fn Modal(props: &ModalProps) -> Html {
|
||||||
.expect("Expected to find a #modal_host element");
|
.expect("Expected to find a #modal_host element");
|
||||||
|
|
||||||
create_portal(
|
create_portal(
|
||||||
html!{ {for props.children.iter()} },
|
props.children.clone(),
|
||||||
modal_host.into(),
|
modal_host.into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ This situation is called "Prop Drilling".
|
||||||
Consider the following example which passes down the theme using props:
|
Consider the following example which passes down the theme using props:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use yew::{html, Children, Component, Context, Html, Properties, function_component};
|
use yew::{html, Component, Context, Html, Properties, function_component};
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
|
@ -51,7 +51,7 @@ fn Navbar(props: &NavbarProps) -> Html {
|
||||||
#[derive(PartialEq, Properties)]
|
#[derive(PartialEq, Properties)]
|
||||||
pub struct ThemeProps {
|
pub struct ThemeProps {
|
||||||
theme: Theme,
|
theme: Theme,
|
||||||
children: Children,
|
children: Html,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[function_component]
|
#[function_component]
|
||||||
|
|
|
@ -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.
|
`Children` is a special prop type that allows you to receive nested `Html` that is provided like html child elements.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use yew::{function_component, html, Html, Properties, Children};
|
use yew::{function_component, html, Html, Properties};
|
||||||
|
|
||||||
#[function_component]
|
#[function_component]
|
||||||
fn App() -> Html {
|
fn App() -> Html {
|
||||||
|
@ -22,7 +22,7 @@ fn App() -> Html {
|
||||||
#[derive(Properties, PartialEq)]
|
#[derive(Properties, PartialEq)]
|
||||||
pub struct Props {
|
pub struct Props {
|
||||||
// highlight-next-line
|
// highlight-next-line
|
||||||
pub children: Children, // the field name `children` is important!
|
pub children: Html, // the field name `children` is important!
|
||||||
}
|
}
|
||||||
|
|
||||||
#[function_component]
|
#[function_component]
|
||||||
|
@ -30,12 +30,8 @@ fn HelloWorld(props: &Props) -> Html {
|
||||||
html! {
|
html! {
|
||||||
<div class="very-stylized-container">
|
<div class="very-stylized-container">
|
||||||
// highlight-next-line
|
// highlight-next-line
|
||||||
{ for props.children.iter() } // you can forward children like this
|
{ props.children.clone() } // you can forward children like this
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Further reading
|
|
||||||
|
|
||||||
- [Advanced ways to handle children](../../advanced-topics/children)
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ struct Props {
|
||||||
#[prop_or_default]
|
#[prop_or_default]
|
||||||
class: Classes,
|
class: Classes,
|
||||||
fill: bool,
|
fill: bool,
|
||||||
children: Children,
|
children: Html,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[function_component]
|
#[function_component]
|
||||||
|
|
|
@ -63,7 +63,7 @@ use yew::prelude::*;
|
||||||
#[derive(PartialEq, Properties)]
|
#[derive(PartialEq, Properties)]
|
||||||
struct Props {
|
struct Props {
|
||||||
id: String,
|
id: String,
|
||||||
children: Children,
|
children: Html,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[function_component]
|
#[function_component]
|
||||||
|
@ -94,7 +94,7 @@ use yew::prelude::*;
|
||||||
#[derive(PartialEq, Properties)]
|
#[derive(PartialEq, Properties)]
|
||||||
struct Props {
|
struct Props {
|
||||||
id: String,
|
id: String,
|
||||||
children: Children,
|
children: Html,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[function_component]
|
#[function_component]
|
||||||
|
@ -108,7 +108,7 @@ fn Container(props: &Props) -> Html {
|
||||||
|
|
||||||
let props = yew::props!(Props {
|
let props = yew::props!(Props {
|
||||||
id: "container-2",
|
id: "container-2",
|
||||||
children: Children::default(),
|
children: Html::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
html! {
|
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
|
## Relevant examples
|
||||||
|
|
||||||
- [Function Todo MVC](https://github.com/yewstack/yew/tree/master/examples/function_todomvc)
|
- [Function Todo MVC](https://github.com/yewstack/yew/tree/master/examples/function_todomvc)
|
||||||
|
|
Loading…
Reference in New Issue