Skip to content

Commit 368e5ea

Browse files
committed
Merge remote-tracking branch 'upstream/master' into feature/opt-keyed-diff
2 parents a40faf4 + 23a166b commit 368e5ea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+856
-8
lines changed

Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
members = [
33
"yew",
44
"yew-components",
5-
"yew-functional",
65
"yew-macro",
76
"yew-validation",
87

@@ -11,6 +10,10 @@ members = [
1110
"yew-router-macro",
1211
"yew-router-route-parser",
1312

13+
# Function components
14+
"yew-functional",
15+
"yew-functional-macro",
16+
1417
# Utilities
1518
"yewtil",
1619
"yewtil-macro",

ci/dictionary.txt

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ composable
1717
Config
1818
declaratively
1919
defs
20+
deps
2021
DerefMut
2122
DOCTYPE
2223
DOCUSAURUS
@@ -50,6 +51,7 @@ Roadmap
5051
rollup
5152
rustc
5253
rustup
54+
stateful
5355
stdweb
5456
struct
5557
structs

docs/advanced-topics/optimizations.md

-5
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,6 @@ identical props using the aforementioned `neq_assign` logic.
9393

9494
Yew doesn't natively support pure or function components, but they are available via external crates.
9595

96-
## Functional components (a.k.a hooks)
97-
98-
Functional components are still in development! There's a
99-
[project board](https://github.com/yewstack/yew/projects/3) detailing their status.
100-
10196
## Keyed DOM nodes when they arrive
10297

10398
## Reducing compile time using workspaces

docs/concepts/function-components.md

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
title: Function Components
3+
sidebar_label: Introduction
4+
description: Introduction to function components
5+
---
6+
7+
:::warning
8+
We're still working on function components and hooks. They're not quite ready to be used yet.
9+
If you'd like to help out, take a look at the [project board](https://github.com/yewstack/yew/projects/3) for a list of things that still need to be done.
10+
:::
11+
12+
13+
Function components are a simplified version of normal components.
14+
They consist of a single function that receives props and determines what should be rendered by returning `Html`.
15+
Basically, it's a component that's been reduced to just the `view` method.
16+
On its own that would be quite limiting because you can only create pure components, but that's where hooks come in.
17+
Hooks allow function components to use state and other Yew features without implementing the `Component` trait.
18+
19+
## Creating function components
20+
21+
The easiest way to create a function component is to add the [`#[function_component]`](function-components/attribute.md) attribute to a function.
22+
23+
```rust
24+
#[function_component(HelloWorld)]
25+
fn hello_world() -> Html {
26+
html! { "Hello world" }
27+
}
28+
```
29+
30+
### Under the hood
31+
32+
Function components consists of two parts.
33+
First, the `FunctionProvider` trait which is comparable to the `Component` trait but it only has a single method called `run`.
34+
The second part is the `FunctionComponent` struct which wraps around the `FunctionProvider` type and turns it into an actual `Component`.
35+
The `#[function_component]` attribute essentially just implements `FunctionProvider` for you and exposes it wrapped in `FunctionComponent`.
36+
37+
### Hooks
38+
39+
Hooks are simply functions that let you “hook into” components' state and/or lifecycle and perform actions. Yew comes with a few pre-defined hooks. You can also create your own.
40+
41+
#### Pre-defined Hooks
42+
43+
Yew comes with the following predefined hooks:
44+
- [`use_state`](function-components/pre-defined-hooks.md#use_state)
45+
- [`use_ref`](function-components/pre-defined-hooks.md#use_ref)
46+
- [`use_reducer`](function-components/pre-defined-hooks.md#use_reducer)
47+
- [`use_reducer_with_init`](function-components/pre-defined-hooks.md#use_reducer_with_init)
48+
- [`use_effect`](function-components/pre-defined-hooks.md#use_effect)
49+
- [`use_effect_with_deps`](function-components/pre-defined-hooks.md#use_effect_with_deps)
50+
51+
#### Custom Hooks
52+
53+
There are cases where you want to define your own hooks for reasons. Yew allows you to define your own hooks which lets you extract your potentially stateful logic from the component into reusable functions.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
title: #[function_component]
3+
description: The #[function_component] attribute
4+
---
5+
6+
7+
The `#[function_component(_)]` turns a normal Rust function into a function component.
8+
Functions with the attribute have to return `Html` and may take a single parameter for the type of props the component should accept.
9+
The parameter type needs to be a reference to a type which implements `Properties` and `PartialEq` (ex. `props: &MyProps`).
10+
If the function doesn't have any parameters the resulting component doesn't accept any props.
11+
12+
The attribute doesn't replace your original function with a component. You need to provide a name as an input to the attribute which will be the identifier of the component.
13+
Assuming you have a function called `chat_container` and you add the attribute `#[function_component(ChatContainer)]` you can use the component like this:
14+
```rust
15+
html! { <ChatContainer /> }
16+
```
17+
18+
## Example
19+
20+
<!--DOCUSAURUS_CODE_TABS-->
21+
<!--With props-->
22+
```rust
23+
#[derive(Properties, Clone, PartialEq)]
24+
pub struct RenderedAtProps {
25+
pub time: String,
26+
}
27+
28+
#[function_component(RenderedAt)]
29+
pub fn rendered_at(props: &RenderedAtProps) -> Html {
30+
html! {
31+
<p>
32+
<b>{ "Rendered at: " }</b>
33+
{ &props.time }
34+
</p>
35+
}
36+
}
37+
```
38+
39+
<!--Without props-->
40+
```rust
41+
#[function_component(App)]
42+
fn app() -> Html {
43+
let (counter, set_counter) = use_state(|| 0);
44+
45+
let onclick = {
46+
let counter = Rc::clone(&counter);
47+
Callback::from(move |_| set_counter(*counter + 1))
48+
};
49+
50+
html! {
51+
<div>
52+
<button onclick=onclick>{ "Increment value" }</button>
53+
<p>
54+
<b>{ "Current value: " }</b>
55+
{ counter }
56+
</p>
57+
</div>
58+
}
59+
}
60+
```
61+
<!--END_DOCUSAURUS_CODE_TABS-->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
title: Custom hooks
3+
description: Defining your own hooks
4+
---
5+
6+
## Defining custom hooks
7+
8+
:::important contribute
9+
Contribute to our docs: Add details about defining custom hooks
10+
11+
Take a look at the [project board](https://github.com/yewstack/yew/projects/3) for details and consider helping out.
12+
:::
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
title: Pre-defined hooks
3+
description: The pre-defined hooks that Yew comes with
4+
---
5+
6+
:::important contribute
7+
Contribute to our docs: Add details about pre-defined hooks
8+
9+
Take a look at the [project board](https://github.com/yewstack/yew/projects/3) for details and consider helping out.
10+
:::
11+
12+
## `use_state`
13+
14+
15+
## `use_ref`
16+
17+
18+
## `use_reducer`
19+
20+
21+
## `use_reducer_with_init`
22+
23+
24+
## `use_effect`
25+
26+
27+
## `use_effect_with_deps`

website/i18n/en.json

+13
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@
2727
"concepts/components/refs": {
2828
"title": "Refs"
2929
},
30+
"concepts/function-components": {
31+
"title": "Function Components",
32+
"sidebar_label": "Introduction"
33+
},
34+
"concepts/function-components/attribute": {
35+
"title": "#[function_component]"
36+
},
37+
"concepts/function-components/custom-hooks": {
38+
"title": "Custom hooks"
39+
},
40+
"concepts/function-components/pre-defined-hooks": {
41+
"title": "Pre-defined hooks"
42+
},
3043
"concepts/html": {
3144
"title": "html!",
3245
"sidebar_label": "Introduction"

website/sidebars.json

+10
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@
4848
"concepts/services/format"
4949
]
5050
},
51+
{
52+
"type": "subcategory",
53+
"label": "Function Components",
54+
"ids": [
55+
"concepts/function-components",
56+
"concepts/function-components/attribute",
57+
"concepts/function-components/pre-defined-hooks",
58+
"concepts/function-components/custom-hooks"
59+
]
60+
},
5161
"concepts/router",
5262
"concepts/agents"
5363
],

yew-functional-macro/Cargo.toml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[package]
2+
name = "yew-functional-macro"
3+
version = "0.1.0"
4+
authors = ["Hamza <[email protected]>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
[lib]
9+
proc-macro = true
10+
11+
[dependencies]
12+
proc-macro2 = "1.0.6"
13+
quote = "1.0"
14+
syn = { version = "1.0.11", features = ["full"] }
15+
16+
# testing
17+
[dev-dependencies]
18+
rustversion = "1.0"
19+
trybuild = "1.0"
20+
yew = { path = "../yew" }
21+
yew-functional = { path = "../yew-functional" }

yew-functional-macro/Makefile.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[tasks.test]
2+
clear = true
3+
toolchain = "1.45.2"
4+
command = "cargo"
5+
args = ["test"]
6+
7+
[tasks.test-overwrite]
8+
extend = "test"
9+
env = { TRYBUILD = "overwrite" }

0 commit comments

Comments
 (0)