Skip to content

Commit 49fa812

Browse files
committed
docs: advocate using IArray instead of Vec in component properties
1 parent ba78970 commit 49fa812

File tree

24 files changed

+1074
-19
lines changed

24 files changed

+1074
-19
lines changed

website/docs/advanced-topics/immutable.mdx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ achieve this we usually wrap things in `Rc`.
1818
Immutable types are a great fit for holding property's values because they can
1919
be cheaply cloned when passed from component to component.
2020

21+
## Common Immutable Types
22+
23+
Yew recommends using the following immutable types from the `implicit-clone` crate:
24+
25+
- `IString` (aliased as `AttrValue` in Yew) - for strings instead of `String`
26+
- `IArray<T>` - for arrays/vectors instead of `Vec<T>`
27+
- `IMap<K, V>` - for maps instead of `HashMap<K, V>`
28+
29+
These types are either reference-counted (`Rc`) or static references, making them very cheap to clone.
30+
2131
## Further reading
2232

2333
- [Immutable example](https://github.com/yewstack/yew/tree/master/examples/immutable)

website/docs/concepts/function-components/properties.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,9 @@ These include, but are not limited to:
341341
**Why is this bad?** Interior mutability (such as with `RefCell`, `Mutex`, etc.) should
342342
_generally_ be avoided. It can cause problems with re-renders (Yew doesn't know when the state has changed)
343343
so you may have to manually force a render. Like all things, it has its place. Use it with caution.
344-
3. Using `Vec` type instead of `IArray`. <br />
345-
**Why is this bad?** `Vec`, just like `String`, can also be expensive to clone. `IArray` is either
346-
a reference-counted slice (`Rc<T>`) or a `&'static [T]`, thus very cheap to clone.<br />
344+
3. Using `Vec<T>` type instead of `IArray<T>`. <br />
345+
**Why is this bad?** `Vec<T>`, just like `String`, can also be expensive to clone. `IArray<T>` is either
346+
a reference-counted slice (`Rc<[T]>`) or a `&'static [T]`, thus very cheap to clone.<br />
347347
**Note**: `IArray` can be imported from [implicit-clone](https://crates.io/crates/implicit-clone)
348348
See that crate to learn more.
349349
4. You tell us. Did you run into an edge-case you wish you knew about earlier? Feel free to create an issue

website/i18n/ja/docusaurus-plugin-content-docs/current/advanced-topics/immutable.mdx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ React と同様に、プロパティは祖先から子孫に伝播されます
1313

1414
イミュータブルタイプは、コンポーネント間でプロパティの値を低コストでクローンできるため、プロパティの値を保持するのに最適です。
1515

16+
## 一般的なイミュータブルタイプ
17+
18+
Yew は `implicit-clone` クレートから以下のイミュータブルタイプの使用を推奨しています:
19+
20+
- `IString`(Yew では `AttrValue` としてエイリアス化)- `String` の代わりに文字列用
21+
- `IArray<T>` - `Vec<T>` の代わりに配列・ベクター用
22+
- `IMap<K, V>` - `HashMap<K, V>` の代わりにマップ用
23+
24+
これらのタイプは参照カウント(`Rc`)または静的参照のいずれかであり、非常に安価にクローンできます。
25+
1626
## さらに読む
1727

1828
- [イミュータブルの例](https://github.com/yewstack/yew/tree/master/examples/immutable)

website/i18n/ja/docusaurus-plugin-content-docs/current/concepts/function-components/properties.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,8 @@ fn main() {
329329
**注意**`AttrValue` は内部的には [implicit-clone](https://crates.io/crates/implicit-clone) からの `IString` です。詳細はそのパッケージを参照してください。
330330
2. 内部可変性を使用する。 <br />
331331
**なぜ悪いのか?** 内部可変性(例えば `RefCell``Mutex` など)は _通常_ 避けるべきです。これにより再レンダリングの問題が発生する可能性があり(Yewは状態が変更されたことを認識しません)、手動で再レンダリングを強制する必要があるかもしれません。すべてのものと同様に、適切な使用場所があります。慎重に使用してください。
332-
3. `Vec` 型を `IArray` の代わりに使用する。 <br />
333-
**なぜ悪いのか?** `Vec``String` と同様にクローンのコストが高いです。`IArray` は参照カウントされたスライス (`Rc<T>`) または `&'static [T]` であり、非常に安価にクローンできます。<br />
332+
3. `Vec<T>` 型を `IArray<T>` の代わりに使用する。 <br />
333+
**なぜ悪いのか?** `Vec<T>``String` と同様にクローンのコストが高いです。`IArray<T>` は参照カウントされたスライス (`Rc<[T]>`) または `&'static [T]` であり、非常に安価にクローンできます。<br />
334334
**注意**`IArray`[implicit-clone](https://crates.io/crates/implicit-clone) からインポートできます。詳細はそのパッケージを参照してください。
335335
4. 新しい発見があるかもしれません。早く知っておきたかったエッジケースに遭遇しましたか?問題を作成するか、このドキュメントに修正のPRを提供してください。
336336

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
title: 'イミュータブルタイプ'
3+
description: 'Yew のイミュータブルデータ構造'
4+
---
5+
6+
## イミュータブルタイプとは?
7+
8+
これらのタイプは、インスタンス化はできるが値を変更することはできないタイプです。値を更新するには、新しい値をインスタンス化する必要があります。
9+
10+
## なぜイミュータブルタイプを使用するのですか?
11+
12+
React と同様に、プロパティは祖先から子孫に伝播されます。これは、各コンポーネントが更新されるたびにプロパティが存在する必要があることを意味します。したがって、プロパティは理想的には簡単にクローンできるべきです。これを実現するために、通常は `Rc` にラップします。
13+
14+
イミュータブルタイプは、コンポーネント間でプロパティの値を低コストでクローンできるため、プロパティの値を保持するのに最適です。
15+
16+
## 一般的なイミュータブルタイプ
17+
18+
Yew は `implicit-clone` クレートから以下のイミュータブルタイプの使用を推奨しています:
19+
20+
- `IString`(Yew では `AttrValue` としてエイリアス化)- `String` の代わりに文字列用
21+
- `IArray<T>` - `Vec<T>` の代わりに配列・ベクター用
22+
- `IMap<K, V>` - `HashMap<K, V>` の代わりにマップ用
23+
24+
これらのタイプは参照カウント(`Rc`)または静的参照のいずれかであり、非常に安価にクローンできます。
25+
26+
## さらに読む
27+
28+
- [イミュータブルの例](https://github.com/yewstack/yew/tree/master/examples/immutable)
29+
- [Crate `implicit-clone`](https://docs.rs/implicit-clone/)
Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
---
2+
title: 'プロパティ (Properties)'
3+
description: '親子コンポーネントの通信'
4+
---
5+
6+
import Tabs from '@theme/Tabs'
7+
import TabItem from '@theme/TabItem'
8+
9+
:::note
10+
11+
プロパティ (Properties) は通常 "Props" と略されます。
12+
13+
:::
14+
15+
プロパティ (Properties) はコンポーネントのパラメータであり、Yew はこれらのパラメータを監視できます。
16+
17+
コンポーネントのプロパティで型を使用する前に、その型は `Properties` トレイトを実装している必要があります。
18+
19+
## リアクティブ性
20+
21+
再レンダリング時に、Yew は仮想DOMを調整する際にプロパティが変更されたかどうかを確認し、ネストされたコンポーネントを再レンダリングする必要があるかどうかを判断します。これにより、Yew は非常にリアクティブなフレームワークと見なされます。親コンポーネントからの変更は常に下位に伝播し、ビューはプロパティ/状態からのデータと常に同期します。
22+
23+
:::tip
24+
25+
まだ [チュートリアル](../../tutorial) を完了していない場合は、このリアクティブ性を自分でテストしてみてください!
26+
27+
:::
28+
29+
## 派生マクロ
30+
31+
Yew は、構造体に `Properties` トレイトを簡単に実装できる派生マクロを提供します。
32+
33+
`Properties` を派生する型は、Yew がデータ比較を行えるように `PartialEq` も実装している必要があります。
34+
35+
```rust
36+
use yew::Properties;
37+
38+
#[derive(Properties, PartialEq)]
39+
pub struct Props {
40+
pub is_loading: bool,
41+
}
42+
```
43+
44+
## 関数コンポーネントでの使用
45+
46+
属性 `#[function_component]` は、関数の引数で Props を選択的に受け取ることを可能にします。それらを提供するには、`html!` マクロ内の属性を通じて割り当てることができます。
47+
48+
<Tabs>
49+
<TabItem value="with-props" label="With Props">
50+
51+
```rust
52+
use yew::{function_component, html, Html, Properties};
53+
54+
#[derive(Properties, PartialEq)]
55+
pub struct Props {
56+
pub is_loading: bool,
57+
}
58+
59+
#[function_component]
60+
fn HelloWorld(props: &Props) -> Html {
61+
html! { <>{"Am I loading? - "}{props.is_loading.clone()}</> }
62+
}
63+
64+
// そしてプロパティを提供します
65+
#[function_component]
66+
fn App() -> Html {
67+
html! {<HelloWorld is_loading={true} />}
68+
}
69+
70+
```
71+
72+
</TabItem>
73+
<TabItem value="no-props" label="No Props">
74+
75+
```rust
76+
use yew::{function_component, html, Html};
77+
78+
79+
80+
81+
82+
#[function_component]
83+
fn HelloWorld() -> Html {
84+
html! { "Hello world" }
85+
}
86+
87+
// 提供するプロパティはありません
88+
#[function_component]
89+
fn App() -> Html {
90+
html! {<HelloWorld />}
91+
}
92+
93+
```
94+
95+
</TabItem>
96+
</Tabs>
97+
98+
## 派生マクロフィールド属性
99+
100+
`Properties` を派生する際、デフォルトではすべてのフィールドが必須です。
101+
以下の属性を使用すると、親コンポーネントがそれらを設定しなかった場合にデフォルト値を提供することができます。
102+
103+
:::tip
104+
属性は Rustdoc によって生成されたドキュメントには表示されません。属性のドキュメント文字列には、その属性がオプションであるかどうか、および特定のデフォルト値があるかどうかを記載する必要があります。
105+
:::
106+
107+
<Tabs>
108+
<TabItem value="prop_or_default" label="#[prop_or_default]">
109+
110+
`Default` トレイトを使用して、フィールド型のデフォルト値でプロパティ値を初期化します。
111+
112+
```rust
113+
use yew::{function_component, html, Html, Properties};
114+
115+
#[derive(Properties, PartialEq)]
116+
pub struct Props {
117+
// highlight-start
118+
#[prop_or_default]
119+
// highlight-end
120+
pub is_loading: bool,
121+
}
122+
123+
#[function_component]
124+
fn HelloWorld(props: &Props) -> Html {
125+
if props.is_loading.clone() {
126+
html! { "Loading" }
127+
} else {
128+
html! { "Hello world" }
129+
}
130+
}
131+
132+
// デフォルト値を使用する
133+
#[function_component]
134+
fn Case1() -> Html {
135+
html! {<HelloWorld />}
136+
}
137+
// またはデフォルト値を上書きしない
138+
#[function_component]
139+
fn Case2() -> Html {
140+
html! {<HelloWorld is_loading={true} />}
141+
}
142+
```
143+
144+
</TabItem>
145+
<TabItem value="prop_or_value" label="#[prop_or(value)]">
146+
147+
`value` を使用してプロパティ値を初期化します。`value` はフィールド型を返す任意の式である可能性があります。
148+
例えば、ブールプロパティをデフォルトで `true` にするには、属性 `#[prop_or(true)]` を使用します。プロパティが構築されるときに、式が評価され、明示的な値が与えられていない場合に適用されます。
149+
150+
```rust
151+
use yew::{function_component, html, Html, Properties};
152+
153+
#[derive(Properties, PartialEq)]
154+
pub struct Props {
155+
// highlight-start
156+
#[prop_or("Bob".to_string())]
157+
// highlight-end
158+
pub name: String,
159+
}
160+
161+
#[function_component]
162+
fn HelloWorld(props: &Props) -> Html {
163+
html! {<>{"Hello world"}{props.name.clone()}</>}
164+
}
165+
166+
// デフォルト値を使用する
167+
#[function_component]
168+
fn Case1() -> Html {
169+
html! {<HelloWorld />}
170+
}
171+
// またはデフォルト値を上書きしない
172+
#[function_component]
173+
fn Case2() -> Html {
174+
html! {<HelloWorld name={"Sam".to_string()} />}
175+
}
176+
```
177+
178+
</TabItem>
179+
<TabItem value="prop_or_else_function" label="#[prop_or_else(function)]">
180+
181+
属性値を初期化するために `function` を呼び出します。`function``FnMut() -> T` シグネチャを持つ必要があり、ここで `T` はフィールドの型です。このプロパティに明示的な値が与えられていない場合、その関数が呼び出されます。
182+
183+
```rust
184+
use yew::{function_component, html, Html, Properties};
185+
186+
fn create_default_name() -> String {
187+
"Bob".to_string()
188+
}
189+
190+
#[derive(Properties, PartialEq)]
191+
pub struct Props {
192+
// highlight-start
193+
#[prop_or_else(create_default_name)]
194+
// highlight-end
195+
pub name: String,
196+
}
197+
198+
#[function_component]
199+
fn HelloWorld(props: &Props) -> Html {
200+
html! {<>{"Hello world"}{props.name.clone()}</>}
201+
}
202+
203+
// デフォルト値を使用する
204+
#[function_component]
205+
fn Case1() -> Html {
206+
html! {<HelloWorld />}
207+
}
208+
// またはデフォルト値を上書きしない
209+
#[function_component]
210+
fn Case2() -> Html {
211+
html! {<HelloWorld name={"Sam".to_string()} />}
212+
}
213+
```
214+
215+
</TabItem>
216+
</Tabs>
217+
218+
## Properties のパフォーマンスオーバーヘッド
219+
220+
内部プロパティは参照カウントされたスマートポインタとして渡されます。これにより、コンポーネントツリー内のプロパティに対して共有ポインタが1つだけ渡されるため、プロパティ全体をクローンする高コストを節約できます。
221+
222+
:::tip
223+
`AttrValue` はプロパティ値に使用するカスタムタイプであり、これにより String やその他のクローンコストが高いタイプとして定義する必要がなくなります。
224+
:::
225+
226+
## Props マクロ
227+
228+
`yew::props!` マクロを使用すると、`html!` マクロと同じ方法でプロパティを構築できます。
229+
230+
このマクロは構造体の式と同じ構文を使用しますが、プロパティや基本式 (`Foo { ..base }`) を使用することはできません。タイプパスはプロパティ (`path::to::Props`) に直接指すことも、コンポーネントの関連プロパティ (`MyComp::Properties`) に指すこともできます。
231+
232+
```rust
233+
use yew::{function_component, html, Html, Properties, props, virtual_dom::AttrValue};
234+
235+
#[derive(Properties, PartialEq)]
236+
pub struct Props {
237+
#[prop_or(AttrValue::from("Bob"))]
238+
pub name: AttrValue,
239+
}
240+
241+
#[function_component]
242+
fn HelloWorld(props: &Props) -> Html {
243+
html! {<>{"Hello world"}{props.name.clone()}</>}
244+
}
245+
246+
#[function_component]
247+
fn App() -> Html {
248+
// highlight-start
249+
let pre_made_props = props! {
250+
Props {} // 名前属性を指定する必要はありません
251+
};
252+
// highlight-end
253+
html! {<HelloWorld ..pre_made_props />}
254+
}
255+
```
256+
257+
## 評価順序
258+
259+
属性は指定された順序で評価されます。以下の例を参照してください:
260+
261+
```rust
262+
#[derive(yew::Properties, PartialEq)]
263+
struct Props { first: usize, second: usize, last: usize }
264+
265+
fn main() {
266+
let mut g = 1..=3;
267+
let props = yew::props!(Props { first: g.next().unwrap(), second: g.next().unwrap(), last: g.next().unwrap() });
268+
269+
assert_eq!(props.first, 1);
270+
assert_eq!(props.second, 2);
271+
assert_eq!(props.last, 3);
272+
}
273+
```
274+
275+
## アンチパターン
276+
277+
ほとんどのRust型はプロパティとして渡すことができますが、避けるべきアンチパターンがいくつかあります。これらには以下が含まれますが、これに限定されません:
278+
279+
1. `String` 型を `AttrValue` の代わりに使用する。 <br />
280+
**なぜ悪いのか?** `String` のクローンは高コストです。プロパティ値がフックやコールバックと一緒に使用される場合、通常クローンが必要です。`AttrValue` は参照カウントされた文字列 (`Rc<str>`) または `&'static str` であり、非常に安価にクローンできます。<br />
281+
**注意**`AttrValue` は内部的には [implicit-clone](https://crates.io/crates/implicit-clone) からの `IString` です。詳細はそのパッケージを参照してください。
282+
2. 内部可変性を使用する。 <br />
283+
**なぜ悪いのか?** 内部可変性(例えば `RefCell``Mutex` など)は _通常_ 避けるべきです。これにより再レンダリングの問題が発生する可能性があり(Yewは状態が変更されたことを認識しません)、手動で再レンダリングを強制する必要があるかもしれません。すべてのものと同様に、適切な使用場所があります。慎重に使用してください。
284+
3. `Vec<T>` 型を `IArray<T>` の代わりに使用する。 <br />
285+
**なぜ悪いのか?** `Vec<T>``String` と同様にクローンのコストが高いです。`IArray<T>` は参照カウントされたスライス (`Rc<[T]>`) または `&'static [T]` であり、非常に安価にクローンできます。<br />
286+
**注意**`IArray<T>`[implicit-clone](https://crates.io/crates/implicit-clone) からインポートできます。詳細はそのパッケージを参照してください。
287+
4. 新しい発見があるかもしれません。早く知っておきたかったエッジケースに遭遇しましたか?問題を作成するか、このドキュメントに修正のPRを提供してください。
288+
289+
## yew-autoprops
290+
291+
[yew-autoprops](https://crates.io/crates/yew-autoprops) は実験的なパッケージで、関数の引数に基づいて動的にProps構造体を作成することを可能にします。プロパティ構造体が再利用されない場合、これは有用かもしれません。

website/i18n/ja/docusaurus-plugin-content-docs/version-0.22/advanced-topics/immutable.mdx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ React と同様に、プロパティは祖先から子孫に伝播されます
1313

1414
イミュータブルタイプは、コンポーネント間でプロパティの値を低コストでクローンできるため、プロパティの値を保持するのに最適です。
1515

16+
## 一般的なイミュータブルタイプ
17+
18+
Yew は `implicit-clone` クレートから以下のイミュータブルタイプの使用を推奨しています:
19+
20+
- `IString`(Yew では `AttrValue` としてエイリアス化)- `String` の代わりに文字列用
21+
- `IArray<T>` - `Vec<T>` の代わりに配列・ベクター用
22+
- `IMap<K, V>` - `HashMap<K, V>` の代わりにマップ用
23+
24+
これらのタイプは参照カウント(`Rc`)または静的参照のいずれかであり、非常に安価にクローンできます。
25+
1626
## さらに読む
1727

1828
- [イミュータブルの例](https://github.com/yewstack/yew/tree/master/examples/immutable)

0 commit comments

Comments
 (0)