Skip to content

Commit

Permalink
update HTML concept to use function components (#2511)
Browse files Browse the repository at this point in the history
* update HTML concept to use function components

* adress comments 1

* fix test

* adress comments 2

* code outside of html
  • Loading branch information
voidpumpkin committed Mar 20, 2022
1 parent 5ececa4 commit 70c9a71
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 626 deletions.
53 changes: 20 additions & 33 deletions website/docs/concepts/html/classes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ title: "Classes"
description: "A handy macro to handle classes"
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

## Classes

Expand Down Expand Up @@ -98,10 +98,7 @@ html! {
## Components that accept classes

```rust
use yew::{
classes, html, Children, Classes, Component,
Context, Html, Properties
};
use yew::prelude::*;

#[derive(PartialEq, Properties)]
struct Props {
Expand All @@ -111,33 +108,23 @@ struct Props {
children: Children,
}

struct MyComponent;

impl Component for MyComponent {
type Message = ();
type Properties = Props;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
let Props {
class,
fill,
children,
} = &ctx.props();
html! {
<div
class={classes!(
"my-container-class",
fill.then(|| Some("my-fill-class")),
class.clone(),
)}
>
{ children.clone() }
</div>
}
#[function_component]
fn MyComponent(props: &Props) -> Html {
let Props {
class,
fill,
children,
} = props;
html! {
<div
class={classes!(
"my-container-class",
fill.then(|| Some("my-fill-class")),
class.clone(),
)}
>
{ children.clone() }
</div>
}
}
```
170 changes: 53 additions & 117 deletions website/docs/concepts/html/components.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,76 +5,50 @@ description: "Create complex layouts with component hierarchies"

## Basic

Any type that implements `Component` can be used in the `html!` macro:
Components can be used in the `html!` macro:

```rust
use yew::{Component, Html, html, Context, Properties};
use yew::prelude::*;

struct MyComponent;

impl Component for MyComponent {
type Message = ();
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
{ "This component has no properties!" }
}
#[function_component]
fn MyComponent() -> Html {
html! {
{ "This component has no properties!" }
}
}

#[derive(Clone, PartialEq, Properties)]
struct Props {
prop1: String,
prop2: String,
user_first_name: String,
user_last_name: String,
}

struct MyComponentWithProps;

impl Component for MyComponentWithProps {
type Message = ();
type Properties = Props;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
html! {
{
format!(
"prop1: {} and prop2: {}",
ctx.props().prop1,
ctx.props().prop2
)
}
}
#[function_component]
fn MyComponentWithProps(props: &Props) -> Html {
let Props { user_first_name, user_last_name } = props;
html! {
<>{"user_first_name: "}{user_first_name}{" and user_last_name: "}{user_last_name}</>
}
}

let props = Props {
prop1: "Hello".to_owned(),
prop2: "World".to_owned(),
let props = Props {
user_first_name: "Bob".to_owned(),
user_last_name: "Smith".to_owned(),
};


html!{
<>
// No properties
<MyComponent />

// With Properties
<MyComponentWithProps prop1="lorem" prop2="ipsum" />
<MyComponentWithProps user_first_name="Sam" user_last_name="Idle" />

// With the whole set of props provided at once
<MyComponentWithProps ..props.clone() />

// With Properties from a variable and specific values overridden
<MyComponentWithProps prop2="lorem" ..props />
<MyComponentWithProps user_last_name="Elm" ..props />
</>
};
```
Expand All @@ -84,30 +58,20 @@ html!{
Components can be passed children if they have a `children` field in their `Properties`.

```rust title="parent.rs"
use yew::{Children, Component, Context, html, Html, Properties};
use yew::prelude::*;

#[derive(PartialEq, Properties)]
struct Props {
id: String,
children: Children,
}

struct Container;

impl Component for Container {
type Message = ();
type Properties = Props;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div id={ctx.props().id.clone()}>
{ ctx.props().children.clone() }
</div>
}
#[function_component]
fn Container(props: &Props) -> Html {
html! {
<div id={props.id.clone()}>
{ props.children.clone() }
</div>
}
}

Expand All @@ -125,34 +89,24 @@ This base expression must occur after any individual props are passed.
When passing a base props expression with a `children` field, the children passed in the `html!` macro overwrite the ones already present in the props.

```rust
use yew::{Children, Component, Context, html, Html, props, Properties};
use yew::prelude::*;

#[derive(PartialEq, Properties)]
struct Props {
id: String,
children: Children,
}

struct Container;

impl Component for Container {
type Message = ();
type Properties = Props;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div id={ctx.props().id.clone()}>
{ ctx.props().children.clone() }
</div>
}
#[function_component]
fn Container(props: &Props) -> Html {
html! {
<div id={props.id.clone()}>
{ props.children.clone() }
</div>
}
}

let props = yew::props!(Container::Properties {
let props = yew::props!(Props {
id: "container-2",
children: Children::default(),
});
Expand All @@ -171,29 +125,20 @@ Nested component properties can be accessed and mutated if the containing compon

```rust
use std::rc::Rc;
use yew::{html, ChildrenWithProps, Component, Context, Html, Properties};
use yew::prelude::*;

#[derive(Clone, PartialEq, Properties)]
pub struct ListItemProps {
value: String,
}

pub struct ListItem;

impl Component for ListItem {
type Message = ();
type Properties = ListItemProps;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<span>
{ ctx.props().value.clone() }
</span>
}
#[function_component]
fn ListItem(props: &ListItemProps) -> Html {
let ListItemProps { value } = props.clone();
html! {
<span>
{value}
</span>
}
}

Expand All @@ -202,25 +147,16 @@ pub struct Props {
pub children: ChildrenWithProps<ListItem>,
}

pub struct List;
impl Component for List {
type Message = ();
type Properties = Props;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
html! {{
for ctx.props().children.iter().map(|mut item| {
let mut props = Rc::make_mut(&mut item.props);
props.value = format!("item-{}", props.value);
item
})
}}
}
#[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" />
Expand All @@ -231,6 +167,6 @@ html! {
```

## Relevant examples
- [Boids](https://github.com/yewstack/yew/tree/master/examples/boids)
- [Router](https://github.com/yewstack/yew/tree/master/examples/router)
- [Store](https://github.com/yewstack/yew/tree/master/examples/store)

- [Function Todo MVC](https://github.com/yewstack/yew/tree/master/examples/function_todomvc)
- [Function Router](https://github.com/yewstack/yew/tree/master/examples/function_router)
13 changes: 6 additions & 7 deletions website/docs/concepts/html/conditional-rendering.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ title: "Conditional rendering"
description: "Rendering nodes conditionally in html!"
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

## If blocks

Expand All @@ -15,7 +14,7 @@ To conditionally render some markup, we wrap it in an `if` block:
<TabItem value="if" label="if">

```rust
use yew::html;
use yew::prelude::*;

html! {
if true {
Expand All @@ -28,7 +27,7 @@ html! {
<TabItem value="if - else" label="if - else">

```rust
use yew::html;
use yew::prelude::*;
let some_condition = true;

html! {
Expand All @@ -44,7 +43,7 @@ html! {
<TabItem value="if let" label="if let">

```rust
use yew::html;
use yew::prelude::*;
let some_text = Some("text");

html! {
Expand All @@ -58,7 +57,7 @@ html! {
<TabItem value="if let else" label="if let else">

```rust
use yew::html;
use yew::prelude::*;
let some_text = Some("text");

html! {
Expand Down
Loading

1 comment on commit 70c9a71

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yew master branch benchmarks (Lower is better)

Benchmark suite Current: 70c9a71 Previous: 5ececa4 Ratio
yew-struct-keyed 01_run1k 161.1465 241.6995 0.67
yew-struct-keyed 02_replace1k 182.751 239.7065 0.76
yew-struct-keyed 03_update10th1k_x16 295.649 347.4445 0.85
yew-struct-keyed 04_select1k 58.903 84.5815 0.70
yew-struct-keyed 05_swap1k 77.38499999999999 93.749 0.83
yew-struct-keyed 06_remove-one-1k 27.522 30.2355 0.91
yew-struct-keyed 07_create10k 2043.425 2774.7185 0.74
yew-struct-keyed 08_create1k-after1k_x2 365.58 542.986 0.67
yew-struct-keyed 09_clear1k_x8 196.6215 238.669 0.82
yew-struct-keyed 21_ready-memory 0.9634475708007812 0.9634475708007812 1
yew-struct-keyed 22_run-memory 1.45648193359375 1.45648193359375 1
yew-struct-keyed 23_update5-memory 1.5030479431152344 1.4602203369140625 1.03
yew-struct-keyed 24_run5-memory 1.5095291137695312 1.5095291137695312 1
yew-struct-keyed 25_run-clear-memory 1.1267204284667969 1.1243438720703125 1.00
yew-struct-keyed 31_startup-ci 1733.06 1789.45 0.97
yew-struct-keyed 32_startup-bt 29.949999999999996 37.67799999999999 0.79
yew-struct-keyed 34_startup-totalbytes 330.5498046875 330.5498046875 1

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.