Skip to content

Commit

Permalink
Introduce immutable string, array and map (#2563)
Browse files Browse the repository at this point in the history
  • Loading branch information
cecton authored Jun 24, 2022
1 parent 6b89e21 commit 7ddf267
Show file tree
Hide file tree
Showing 17 changed files with 357 additions and 205 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ members = [
"examples/web_worker_fib",
"examples/ssr_router",
"examples/suspense",
"examples/immutable",

# Tools
"tools/benchmark-struct",
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ As an example, check out the TodoMVC example here: <https://examples.yew.rs/todo
| [function_todomvc](function_todomvc) | F | Implementation of [TodoMVC](http://todomvc.com/) using function components and hooks. |
| [futures](futures) | S | Demonstrates how you can use futures and async code with Yew. Features a Markdown renderer. |
| [game_of_life](game_of_life) | S | Implementation of [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) |
| [immutable](immutable) | SF | Using immutable types in components. |
| [inner_html](inner_html) | S | Embeds an external document as raw HTML by manually managing the element |
| [js_callback](js_callback) | F | Interacts with JavaScript code |
| [keyed_list](keyed_list) | S | Demonstrates how to use keys to improve the performance of lists |
Expand Down
12 changes: 12 additions & 0 deletions examples/immutable/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "immutable"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
implicit-clone = { version = "0.2", features = ["map"] }
wasm-bindgen = "0.2"
web-sys = "0.3"
yew = { path = "../../packages/yew", features = ["csr"] }
5 changes: 5 additions & 0 deletions examples/immutable/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Immutable Example

[![Demo](https://img.shields.io/website?label=demo&url=https%3A%2F%2Fexamples.yew.rs%2Fimmutable)](https://examples.yew.rs/immutable)

This is a technical demonstration for how to use immutables types in Yew.
13 changes: 13 additions & 0 deletions examples/immutable/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<title>Yew • Immutable</title>
<link data-trunk rel="scss" href="index.scss"/>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@900&display=swap" rel="stylesheet">
</head>

<body></body>

</html>
11 changes: 11 additions & 0 deletions examples/immutable/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
$font-stack: Roboto, sans-serif;
$primary-color: #f5f5f5;

body {
font: 100% $font-stack;
color: black;
background-color: $primary-color;
margin: 0 auto;
min-width: 230px;
max-width: 550px;
}
54 changes: 54 additions & 0 deletions examples/immutable/src/array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use implicit_clone::unsync::*;
use wasm_bindgen::{JsCast, UnwrapThrowExt};
use web_sys::{HtmlInputElement, KeyboardEvent};
use yew::prelude::*;

#[derive(Properties, PartialEq)]
struct FolksViewProps {
folks: IArray<IString>,
}

#[function_component(FolksView)]
fn folks_view(props: &FolksViewProps) -> Html {
html! {
<>
<p>{"Hello to:"}</p>
<ul>
{ for props.folks.iter().map(|s| html!(<li>{s}</li>)) }
</ul>
</>
}
}

#[function_component(ArrayExample)]
pub fn array_example() -> Html {
let folks = use_state(IArray::<IString>::default);
let onkeyup = {
let folks = folks.clone();
Callback::from(move |e: KeyboardEvent| {
if e.key() == "Enter" {
let event: Event = e.dyn_into().unwrap_throw();
let event_target = event.target().unwrap_throw();
let target: HtmlInputElement = event_target.dyn_into().unwrap_throw();
let name = target.value();
target.set_value("");

folks.set(
folks
.iter()
.chain(std::iter::once(IString::from(name)))
.collect(),
);
}
})
};

html! {
<>
<h2>{"Input"}</h2>
<input {onkeyup} />
<h2>{"Output"}</h2>
<FolksView folks={&*folks} />
</>
}
}
29 changes: 29 additions & 0 deletions examples/immutable/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
mod array;
mod map;
mod string;

use yew::prelude::*;

use self::array::*;
use self::map::*;
use self::string::*;

#[function_component]
fn App() -> Html {
html! {
<>
<h1>{ "IString Example" }</h1>
<StringExample />
<hr/>
<h1>{ "IArray Example" }</h1>
<ArrayExample />
<hr/>
<h1>{ "IMap Example" }</h1>
<MapExample />
</>
}
}

fn main() {
yew::Renderer::<App>::new().render();
}
83 changes: 83 additions & 0 deletions examples/immutable/src/map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use implicit_clone::unsync::*;
use wasm_bindgen::{JsCast, UnwrapThrowExt};
use web_sys::{HtmlInputElement, KeyboardEvent};
use yew::prelude::*;

#[derive(Properties, PartialEq)]
struct DisplayProps {
values: IMap<u32, IString>,
}

#[function_component]
fn Display(props: &DisplayProps) -> Html {
html! {
<>
<p>{"Hello to:"}</p>
<ul>
{ for props.values.iter().map(|(i, s)| html!(<li>{i}{" => "}{s}</li>)) }
</ul>
</>
}
}

pub struct MapExample {
values: IMap<u32, IString>,
}

pub enum MapExampleMessage {
AddName(String),
Noop,
}

impl Component for MapExample {
type Message = MapExampleMessage;
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
Self {
values: Default::default(),
}
}

fn update(&mut self, _: &Context<Self>, msg: Self::Message) -> bool {
match msg {
MapExampleMessage::AddName(name) => {
self.values = self
.values
.iter()
.chain(std::iter::once((
self.values.len() as u32,
IString::from(name),
)))
.collect();
true
}
MapExampleMessage::Noop => false,
}
}

fn view(&self, ctx: &Context<Self>) -> Html {
let link = ctx.link();
let onkeyup = link.callback(|e: KeyboardEvent| {
if e.key() == "Enter" {
let event: Event = e.dyn_into().unwrap_throw();
let event_target = event.target().unwrap_throw();
let target: HtmlInputElement = event_target.dyn_into().unwrap_throw();
let value = target.value();
target.set_value("");
MapExampleMessage::AddName(value)
} else {
MapExampleMessage::Noop
}
});

html! {
<>
<h2>{"Input"}</h2>
<input {onkeyup} />
<h2>{"Output"}</h2>
<Display values={&self.values} />
</>
}
}
}
63 changes: 63 additions & 0 deletions examples/immutable/src/string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use implicit_clone::unsync::*;
use wasm_bindgen::{JsCast, UnwrapThrowExt};
use web_sys::{HtmlInputElement, InputEvent};
use yew::prelude::*;

#[derive(Properties, PartialEq)]
struct DisplayProps {
name: IString,
}

#[function_component]
fn Display(props: &DisplayProps) -> Html {
html! {
<p>{"Hello "}{&props.name}{"!"}</p>
}
}

pub struct StringExample {
name: IString,
}

pub enum StringExampleMessage {
UpdateName(String),
}

impl Component for StringExample {
type Message = StringExampleMessage;
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
Self {
name: "World".into(),
}
}

fn update(&mut self, _: &Context<Self>, msg: Self::Message) -> bool {
match msg {
StringExampleMessage::UpdateName(name) => {
self.name = name.into();
true
}
}
}

fn view(&self, ctx: &Context<Self>) -> Html {
let link = ctx.link();
let oninput = link.callback(|e: InputEvent| {
let event: Event = e.dyn_into().unwrap_throw();
let event_target = event.target().unwrap_throw();
let target: HtmlInputElement = event_target.dyn_into().unwrap_throw();
StringExampleMessage::UpdateName(target.value())
});

html! {
<>
<h2>{"Input"}</h2>
<input value={&self.name} {oninput} />
<h2>{"Output"}</h2>
<Display name={&self.name} />
</>
}
}
}
12 changes: 6 additions & 6 deletions packages/yew-macro/tests/html_macro/component-fail.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -345,11 +345,11 @@ error[E0277]: the trait bound `{integer}: IntoPropValue<String>` is not satisfie
| ^ the trait `IntoPropValue<String>` is not implemented for `{integer}`
|
= help: the following implementations were found:
<&'static str as IntoPropValue<AttrValue>>
<&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::IMap<K, V>>>
<&'static [T] as IntoPropValue<implicit_clone::unsync::IArray<T>>>
<&'static str as IntoPropValue<Classes>>
<&'static str as IntoPropValue<Option<AttrValue>>>
<&'static str as IntoPropValue<Option<String>>>
and 27 others
and 31 others

error[E0277]: the trait bound `{integer}: IntoPropValue<String>` is not satisfied
--> tests/html_macro/component-fail.rs:79:34
Expand All @@ -358,11 +358,11 @@ error[E0277]: the trait bound `{integer}: IntoPropValue<String>` is not satisfie
| ^ the trait `IntoPropValue<String>` is not implemented for `{integer}`
|
= help: the following implementations were found:
<&'static str as IntoPropValue<AttrValue>>
<&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::IMap<K, V>>>
<&'static [T] as IntoPropValue<implicit_clone::unsync::IArray<T>>>
<&'static str as IntoPropValue<Classes>>
<&'static str as IntoPropValue<Option<AttrValue>>>
<&'static str as IntoPropValue<Option<String>>>
and 27 others
and 31 others

error[E0308]: mismatched types
--> tests/html_macro/component-fail.rs:80:31
Expand Down
Loading

1 comment on commit 7ddf267

@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: 7ddf267 Previous: 6b89e21 Ratio
yew-struct-keyed 01_run1k 212.0465 153.958 1.38
yew-struct-keyed 02_replace1k 228.927 160.041 1.43
yew-struct-keyed 03_update10th1k_x16 403.8075 265.0145 1.52
yew-struct-keyed 04_select1k 59.569500000000005 39.68 1.50
yew-struct-keyed 05_swap1k 90.63 64.8015 1.40
yew-struct-keyed 06_remove-one-1k 29.572000000000003 24.304 1.22
yew-struct-keyed 07_create10k 3614.9945 2573.5415000000003 1.40
yew-struct-keyed 08_create1k-after1k_x2 532.1935000000001 343.18 1.55
yew-struct-keyed 09_clear1k_x8 235.6035 145.0945 1.62
yew-struct-keyed 21_ready-memory 1.4694786071777344 1.4694786071777344 1
yew-struct-keyed 22_run-memory 1.662761688232422 1.6625480651855469 1.00
yew-struct-keyed 23_update5-memory 1.7005348205566406 1.6997566223144531 1.00
yew-struct-keyed 24_run5-memory 1.7159767150878906 1.7159767150878906 1
yew-struct-keyed 25_run-clear-memory 1.3292694091796875 1.3307838439941406 1.00
yew-struct-keyed 31_startup-ci 1731.464 1880.825 0.92
yew-struct-keyed 32_startup-bt 34.41199999999999 41.67199999999998 0.83
yew-struct-keyed 33_startup-mainthreadcost 313.48 192.8 1.63
yew-struct-keyed 34_startup-totalbytes 332.2724609375 332.2724609375 1

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

Please sign in to comment.