Skip to content

Commit

Permalink
Convert components concept docs from SC to FC (#2434)
Browse files Browse the repository at this point in the history
* Convert components concept docs from SC to FC
- moved struct components to advanced topics
- added docs about HOC for Suspense and Context
- added a ease-in topic before components that introduces
HTML/CSS/JS in yew
- edit components concept to use function components

* translations

* fix todo links

* fix tests

* spelling bee
  • Loading branch information
voidpumpkin authored Feb 7, 2022
1 parent bd373d2 commit 6366925
Show file tree
Hide file tree
Showing 39 changed files with 1,648 additions and 712 deletions.
12 changes: 9 additions & 3 deletions packages/yew/src/functional/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
//! Function components are a simplified version of normal components.
//! They consist of a single function annotated with the attribute `#[function_component(_)]`
//! They consist of a single function annotated with the attribute `#[function_component]`
//! that receives props and determines what should be rendered by returning [`Html`](crate::Html).
//!
//! Functions with the attribute have to return `Html` and may take a single parameter for the type of props the component should accept.
//! The parameter type needs to be a reference to a `Properties` type (ex. `props: &MyProps`).
//! If the function doesn't have any parameters the resulting component doesn't accept any props.
//!
//! Just mark the component with the attribute. The component will be named after the function.
//!
//! ```rust
//! # use yew::prelude::*;
//! #
//! #[function_component(HelloWorld)]
//! fn hello_world() -> Html {
//! #[function_component]
//! fn HelloWorld() -> Html {
//! html! { "Hello world" }
//! }
//! ```
Expand Down
File renamed without changes.
82 changes: 82 additions & 0 deletions website/docs/advanced-topics/struct-components/hoc.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
title: "Higher Order Components"
---

There are several cases where Struct components dont directly support a feature (ex. Suspense) or require a lot of boiler plate to use the features (ex. Context).

In those cases it is recommended to create function components that are higher order components.

## Higher Order Components Definition

Higher Order Components are components that dont add any new Html and only wrap some other component to provide extra functionality.

### Example

Hook into Context and pass it down to a struct component

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

#[derive(Clone, Debug, PartialEq)]
struct Theme {
foreground: String,
background: String,
}

#[function_component]
pub fn App() -> Html {
let ctx = use_state(|| Theme {
foreground: "#000000".to_owned(),
background: "#eeeeee".to_owned(),
});

html! {
<ContextProvider<Theme> context={(*ctx).clone()}>
<ThemedButtonHOC />
</ContextProvider<Theme>>
}
}

// highlight-start
#[function_component]
pub fn ThemedButtonHOC() -> Html {
let theme = use_context::<Theme>().expect("no ctx found");

html! {<ThemedButtonStructComponent {theme} />}
}
// highlight-end

#[derive(Properties, PartialEq)]
pub struct Props {
pub theme: Theme,
}

struct ThemedButtonStructComponent;

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

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

fn view(&self, ctx: &Context<Self>) -> Html {
let theme = &ctx.props().theme;
html! {
<button style={format!(
"background: {}; color: {};",
theme.background,
theme.foreground
)}
>
{ "Click me!" }
</button>
}
}
}




```
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
title: "Introduction"
description: "Components in Yew"
slug: /concepts/components
---

## What are Components?
Expand All @@ -21,7 +20,7 @@ much stricter. It also provides super-powers like conditional rendering and rend

## Passing data to a component

Yew components use *props* to communicate between parent and children. A parent component may pass any data as props to
Yew components use _props_ to communicate between parent and children. A parent component may pass any data as props to
its children. Props are similar to HTML attributes but any Rust type can be passed as props.

:::info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The following attributes allow you to give your props initial values which will

:::tip
Attributes aren't visible in Rustdoc generated documentation.
The docstrings of your properties should mention whether a prop is optional and if it has a special default value.
The doc strings of your properties should mention whether a prop is optional and if it has a special default value.
:::

#### `#[prop_or_default]`
Expand Down
File renamed without changes.
File renamed without changes.
104 changes: 104 additions & 0 deletions website/docs/concepts/basic-web-technologies/css.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
title: "CSS with classes!"
description: "A handy macro to handle classes"
comment: "Keep this file as short and simple as possible. Its purpose is to ease in the reader into components in Yew instead of providing proper API docs"
---

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

> Yew mostly operates on the idea of keeping everything that a reusable piece of
> UI may need, in one place - rust files. But also seeks to stay close to the
> original look of the technology.
Yew does not provide css in rs solutions natively, but helps with css by providing
programmatic ways to interact with css classes.

## Classes

The struct `Classes` simplifies use of HTML classes:

<Tabs>
<TabItem value="Literal" label="Literal">

```rust
use yew::{classes, html};

html! {
<div class={classes!("container")}></div>
};
```

</TabItem>
<TabItem value="Multiple" label="Multiple">

```rust
use yew::{classes, html};

html! {
<div class={classes!("class-1", "class-2")}></div>
};
```

</TabItem>
<TabItem value="String" label="String">

```rust
use yew::{classes, html};

html! {
<div class={classes!(String::from("class-1 class-2"))}></div>
};
```

</TabItem>
<TabItem value="Optional" label="Optional">

```rust
use yew::{classes, html};

html! {
<div class={classes!(Some("class"))} />
};
```

</TabItem>
<TabItem value="Vector" label="Vector">

```rust
use yew::{classes, html};

html! {
<div class={classes!(vec!["class-1", "class-2"])}></div>
};
```

</TabItem>
<TabItem value="Slice" label="Slice">

```rust
use yew::{classes, html};

html! {
<div class={classes!(["class-1", "class-2"].as_ref())}></div>
};
```

</TabItem>
</Tabs>

We will expand upon this concept in [more CSS](../../more/css).

## Inline Styles

Currently Yew does not provide any help with inline styles natively:

```rust
use yew::{classes, html};

html! {
<div styles="color: red;"></div>
};
```

We will expand upon this concept in [more CSS](../../more/css).
88 changes: 88 additions & 0 deletions website/docs/concepts/basic-web-technologies/html.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: "HTML with html!"
description: "Its HTML but not quite!"
comment: "Keep this file as short and simple as possible. Its purpose is to ease in the reader into components in Yew instead of providing proper API docs"
---

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

> Yew mostly operates on the idea of keeping everything that a reusable piece of
> UI may need, in one place - rust files. But also seeks to stay close to the
> original look of the technology.
For HTML we achieve this by providing the `html!` macro:

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

let my_header: Html = html!{<img src="img_girl.jpg" alt="Girl in a jacket" width="500" height="600" />};
```

`html!` macro allows you to write html generation as if it was in a `.html` file and then behind the scenes by yew gets turned into internal builder patterns that generate all DOM nodes.

As it is part of rust code it provides a easy way to switch from html to rust by applying curly brackets:

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

let header_text = "Hello world".to_string();
let header_html: Html = html!{<h1>{header_text}</h1>};

let count: usize = 5;
let counter_html: Html = html!{<p>{"My age is: "}{count}</p>};

let combined_html: Html = html!{<div>{header_html}{counter_html}</div>};
```

One rule major rule comes with use of `html!` - you can only return 1 wrapping node:

<Tabs>
<TabItem value="Valid" label="Valid">

```rust
use yew::html;

html! {
<div>
<div></div>
<p></p>
</div>
};

```

</TabItem>

<TabItem value="Invalid" label="Invalid">

```rust, compile_fail
use yew::html;
// error: only one root html element allowed
html! {
<div></div>
<p></p>
};
```

</TabItem>
</Tabs>

To help with this rule and avoid `div` abuse `html!` allows fragments. Fragments are empty tags that do not provide any html result:

```rust
use yew::html;

html! {
<>
<div></div>
<p></p>
</>
};

```

We will introduce Yew and HTML further in depth in [more HTML](../html).
56 changes: 56 additions & 0 deletions website/docs/concepts/basic-web-technologies/js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: "JS with RS"
description: "Javascript with Rust"
comment: "Keep this file as short and simple as possible. Its purpose is to ease in the reader into components in Yew instead of providing proper API docs"
---

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

> Yew mostly operates on the idea of keeping everything that a reusable piece of
> UI may need, in one place - rust files. But also seeks to stay close to the
> original look of the technology.
Sadly as of today WebAssembly is not feature-complete for DOM interactions. This means even in Yew we sometimes rely on calling Javascript.

## wasm-bindgen

[`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) is a library and tool that allows to call javascript from rust and rust from javascript.

We highly recommend you give a look to their [documentation](https://rustwasm.github.io/docs/wasm-bindgen/)

We will also expand upon this concept in the [more wasm-bindgen](../wasm-bindgen).

## web-sys

The [`web-sys` crate](https://crates.io/crates/web-sys) provides bindings for Web APIs and allows us to write Javascript code in a rustyfied and safe way.

Example:

<Tabs>
<TabItem value="JS" label="JS">

```js
let document = window.document;
```

</TabItem>

<TabItem value="RS" label="RS">

```rust ,no_run
use wasm_bindgen::UnwrapThrowExt;
use web_sys::window;

let document = window()
.expect_throw("window is undefined")
.document()
.expect_throw("document is undefined");
```

</TabItem>
</Tabs>

Once again we highly recommend you give a look to their [documentation](https://rustwasm.github.io/docs/wasm-bindgen/)

We will also expand upon this concept in the [more wasm-bindgen](../wasm-bindgen).
Loading

1 comment on commit 6366925

@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: 6366925 Previous: bd373d2 Ratio
yew-struct-keyed 01_run1k 213.4295 162.92700000000002 1.31
yew-struct-keyed 02_replace1k 234.239 172.9105 1.35
yew-struct-keyed 03_update10th1k_x16 448.5355 312.041 1.44
yew-struct-keyed 04_select1k 90.4245 68.25 1.32
yew-struct-keyed 05_swap1k 99.735 92.3215 1.08
yew-struct-keyed 06_remove-one-1k 30.8775 30.8305 1.00
yew-struct-keyed 07_create10k 2698.133 2175.1040000000003 1.24
yew-struct-keyed 08_create1k-after1k_x2 557.3240000000001 432.8855 1.29
yew-struct-keyed 09_clear1k_x8 251.2665 210.3835 1.19
yew-struct-keyed 21_ready-memory 0.9634513854980468 0.9634513854980468 1
yew-struct-keyed 22_run-memory 1.4578094482421875 1.4578094482421875 1
yew-struct-keyed 23_update5-memory 1.4615478515625 1.5068473815917969 0.97
yew-struct-keyed 24_run5-memory 1.510845184326172 1.510845184326172 1
yew-struct-keyed 25_run-clear-memory 1.1287879943847656 1.1287879943847656 1
yew-struct-keyed 31_startup-ci 1857.71075 1882.03 0.99
yew-struct-keyed 32_startup-bt 31.641999999999992 40.54199999999999 0.78
yew-struct-keyed 34_startup-totalbytes 367.962890625 367.962890625 1

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

Please sign in to comment.