Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Components v2 (2) #1961

Merged
merged 39 commits into from
Aug 25, 2021
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
9043be0
Start rewrite
ranile Jul 19, 2021
47956ec
Rc > cloning props
ranile Jul 19, 2021
cd70b5c
fmt + rm useless file
ranile Jul 19, 2021
dbc99d9
move props inside `Context`
ranile Jul 20, 2021
ce68de2
router compiles
ranile Jul 20, 2021
98b58a6
fix boids example
ranile Jul 20, 2021
7e232ef
fix counter example
ranile Jul 20, 2021
a789153
fix crm example
ranile Jul 20, 2021
3809b0a
fix dyn_create_destroy_apps example
ranile Jul 20, 2021
c7dbc53
fix file_upload example
ranile Jul 20, 2021
e870939
fix futures example
ranile Jul 20, 2021
ee6a6af
fix game_of_life example
ranile Jul 20, 2021
5d9e411
fix inner_html example
ranile Jul 20, 2021
debabd2
fix js_callback example
ranile Jul 20, 2021
ea8c3d8
fix mount_point example
ranile Jul 20, 2021
4809ed2
fix keyed_list example
ranile Jul 20, 2021
b9126aa
fix web_gl example
ranile Jul 20, 2021
a2af608
fix two_apps example
ranile Jul 20, 2021
9d23724
fix todomvc example
ranile Jul 20, 2021
5b3567b
fix timer example
ranile Jul 21, 2021
fa03e61
fix store example
ranile Jul 21, 2021
bb546d8
fix nested_list example
ranile Jul 21, 2021
466deec
fix node_refs example
ranile Jul 21, 2021
0786649
fix pub_sub example
ranile Jul 21, 2021
183707d
fix multi_thread example
ranile Jul 21, 2021
b14d803
don't call `changed` if props weren't changed
ranile Jul 21, 2021
16b66d5
formatting
ranile Jul 21, 2021
774c279
fix doc tests, remove neq_assign
ranile Jul 21, 2021
40ee36e
update router example, fix neq_assign compile errors
ranile Jul 21, 2021
c4d74ef
fix macro/rest of doc tests
ranile Jul 21, 2021
afb3810
start updating documentation
ranile Jul 21, 2021
4ab9cbb
`Component`'s documentation
ranile Jul 21, 2021
ccf10f3
Apply suggestions from code review
ranile Jul 22, 2021
dea6b3d
Apply suggestions from code review (part 2)
ranile Jul 22, 2021
712636b
Apply suggestions from code review (part 3)
ranile Jul 23, 2021
5bf16f5
fix context
ranile Jul 23, 2021
01eb192
clippy
ranile Aug 14, 2021
4f2c623
Merge branch 'master' into comp-rewrite
ranile Aug 24, 2021
4c188eb
post merge fixes
ranile Aug 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 10 additions & 16 deletions examples/boids/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use settings::Settings;
use simulation::Simulation;
use slider::Slider;
use yew::{html, Component, ComponentLink, Html, ShouldRender};
use yew::html::Scope;
use yew::{html, Component, Context, Html, ShouldRender};

mod boid;
mod math;
Expand All @@ -17,7 +18,6 @@ pub enum Msg {
}

pub struct Model {
link: ComponentLink<Self>,
settings: Settings,
generation: usize,
paused: bool,
Expand All @@ -26,16 +26,15 @@ impl Component for Model {
type Message = Msg;
type Properties = ();

fn create(_props: Self::Properties, link: ComponentLink<Self>) -> Self {
fn create(_ctx: &Context<Self>) -> Self {
Self {
link,
settings: Settings::load(),
generation: 0,
paused: false,
}
}

fn update(&mut self, msg: Self::Message) -> ShouldRender {
fn update(&mut self, _ctx: &Context<Self>, msg: Msg) -> ShouldRender {
match msg {
Msg::ChangeSettings(settings) => {
self.settings = settings;
Expand All @@ -58,11 +57,7 @@ impl Component for Model {
}
}

fn change(&mut self, _props: Self::Properties) -> ShouldRender {
false
}

fn view(&self) -> Html {
fn view(&self, ctx: &Context<Self>) -> Html {
let Self {
ref settings,
generation,
Expand All @@ -74,18 +69,17 @@ impl Component for Model {
<>
<h1 class="title">{ "Boids" }</h1>
<Simulation settings={settings.clone()} {generation} {paused} />
{ self.view_panel() }
{ self.view_panel(ctx.link()) }
</>
}
}
}
impl Model {
fn view_panel(&self) -> Html {
let link = &self.link;
fn view_panel(&self, link: &Scope<Self>) -> Html {
let pause_text = if self.paused { "Resume" } else { "Pause" };
html! {
<div class="panel">
{ self.view_settings() }
{ self.view_settings(link) }
<div class="panel__buttons">
<button onclick={link.callback(|_| Msg::TogglePause)}>{ pause_text }</button>
<button onclick={link.callback(|_| Msg::ResetSettings)}>{ "Use Defaults" }</button>
Expand All @@ -95,8 +89,8 @@ impl Model {
}
}

fn view_settings(&self) -> Html {
let Self { link, settings, .. } = self;
fn view_settings(&self, link: &Scope<Self>) -> Html {
let Self { settings, .. } = self;

// This helper macro creates a callback which applies the new value to the current settings and sends `Msg::ChangeSettings`.
// Thanks to this, we don't need to have "ChangeBoids", "ChangeCohesion", etc. messages,
Expand Down
61 changes: 22 additions & 39 deletions examples/boids/src/simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::boid::Boid;
use crate::math::Vector2D;
use crate::settings::Settings;
use gloo::timers::callback::Interval;
use yew::{html, Component, ComponentLink, Html, Properties, ShouldRender};
use yew::{html, Component, Context, Html, Properties, ShouldRender};

pub const SIZE: Vector2D = Vector2D::new(1600.0, 1000.0);

Expand All @@ -22,44 +22,37 @@ pub struct Props {

#[derive(Debug)]
pub struct Simulation {
props: Props,
link: ComponentLink<Self>,
boids: Vec<Boid>,
interval: Interval,
}
impl Component for Simulation {
type Message = Msg;
type Properties = Props;

fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
let settings = &props.settings;
fn create(ctx: &Context<Self>) -> Self {
let settings = &ctx.props().settings;
let boids = (0..settings.boids)
.map(|_| Boid::new_random(settings))
.collect();

let interval = {
let link = link.clone();
let link = ctx.link().clone();
Interval::new(settings.tick_interval_ms as u32, move || {
link.send_message(Msg::Tick)
})
};

Self {
props,
link,
boids,
interval,
}
Self { boids, interval }
}

fn update(&mut self, msg: Self::Message) -> ShouldRender {
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Tick => {
let Props {
ref settings,
paused,
..
} = self.props;
} = *ctx.props();

if paused {
false
Expand All @@ -71,36 +64,26 @@ impl Component for Simulation {
}
}

fn change(&mut self, props: Self::Properties) -> ShouldRender {
if props == self.props {
false
} else {
if props.generation != self.props.generation {
// generation changed; restart from scratch.
self.boids.clear();
}
fn changed(&mut self, ctx: &Context<Self>) -> ShouldRender {
self.boids.clear();

let settings = &props.settings;
self.boids
.resize_with(settings.boids, || Boid::new_random(settings));
let settings = &ctx.props().settings;
self.boids
.resize_with(settings.boids, || Boid::new_random(settings));

if settings.tick_interval_ms != self.props.settings.tick_interval_ms {
// as soon as the previous task is dropped it is cancelled.
// We don't need to worry about manually stopping it.
self.interval = {
let link = self.link.clone();
Interval::new(settings.tick_interval_ms as u32, move || {
link.send_message(Msg::Tick)
})
}
}
// as soon as the previous task is dropped it is cancelled.
// We don't need to worry about manually stopping it.
self.interval = {
let link = ctx.link().clone();
Interval::new(settings.tick_interval_ms as u32, move || {
link.send_message(Msg::Tick)
})
};

self.props = props;
true
}
true
}

fn view(&self) -> Html {
fn view(&self, _ctx: &Context<Self>) -> Html {
let view_box = format!("0 0 {} {}", SIZE.x, SIZE.y);

html! {
Expand Down
21 changes: 5 additions & 16 deletions examples/boids/src/slider.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::cell::Cell;
use yew::{html, Callback, Component, ComponentLink, Html, InputData, Properties, ShouldRender};
use yew::{html, Callback, Component, Context, Html, InputData, Properties, ShouldRender};

thread_local! {
static SLIDER_ID: Cell<usize> = Cell::default();
Expand All @@ -25,34 +25,23 @@ pub struct Props {
}

pub struct Slider {
props: Props,
id: usize,
}
impl Component for Slider {
type Message = ();
type Properties = Props;

fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
fn create(_ctx: &Context<Self>) -> Self {
Self {
props,
id: next_slider_id(),
}
}

fn update(&mut self, _msg: Self::Message) -> ShouldRender {
fn update(&mut self, _ctx: &Context<Self>, _msg: Self::Message) -> ShouldRender {
unimplemented!()
}

fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}

fn view(&self) -> Html {
fn view(&self, ctx: &Context<Self>) -> Html {
let Props {
label,
value,
Expand All @@ -62,7 +51,7 @@ impl Component for Slider {
min,
max,
step,
} = self.props;
} = *ctx.props();

let precision = precision.unwrap_or_else(|| if percentage { 1 } else { 0 });

Expand Down
21 changes: 8 additions & 13 deletions examples/counter/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use js_sys::Date;
use weblog::console_log;
use yew::{html, Component, ComponentLink, Html, ShouldRender};
use yew::{html, Component, Context, Html, ShouldRender};

// Define the possible messages which can be sent to the component
pub enum Msg {
Expand All @@ -9,19 +9,18 @@ pub enum Msg {
}

pub struct Model {
link: ComponentLink<Self>,
value: i64, // This will store the counter value
}

impl Component for Model {
type Message = Msg;
type Properties = ();

fn create(_props: Self::Properties, link: ComponentLink<Self>) -> Self {
Self { link, value: 0 }
fn create(_ctx: &Context<Self>) -> Self {
Self { value: 0 }
}

fn update(&mut self, msg: Self::Message) -> ShouldRender {
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Increment => {
self.value += 1;
Expand All @@ -36,26 +35,22 @@ impl Component for Model {
}
}

fn change(&mut self, _props: Self::Properties) -> ShouldRender {
false
}

fn view(&self) -> Html {
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div>
<div class="panel">
// A button to send the Increment message
<button class="button" onclick={self.link.callback(|_| Msg::Increment)}>
<button class="button" onclick={ctx.link().callback(|_| Msg::Increment)}>
{ "+1" }
</button>

// A button to send the Decrement message
<button onclick={self.link.callback(|_| Msg::Decrement)}>
<button onclick={ctx.link().callback(|_| Msg::Decrement)}>
{ "-1" }
</button>

// A button to send two Increment messages
<button onclick={self.link.batch_callback(|_| vec![Msg::Increment, Msg::Increment])}>
<button onclick={ctx.link().batch_callback(|_| vec![Msg::Increment, Msg::Increment])}>
{ "+1, +1" }
</button>

Expand Down
30 changes: 8 additions & 22 deletions examples/crm/src/add_client.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use crate::Client;
use yew::{
classes, html, Callback, Component, ComponentLink, Html, InputData, Properties, ShouldRender,
};
use yew::{classes, html, Callback, Component, Context, Html, InputData, Properties, ShouldRender};

#[derive(Debug)]
pub enum Msg {
Expand All @@ -19,23 +17,19 @@ pub struct Props {
}

pub struct AddClientForm {
props: Props,
link: ComponentLink<Self>,
client: Client,
}
impl Component for AddClientForm {
type Message = Msg;
type Properties = Props;

fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
fn create(_ctx: &Context<Self>) -> Self {
Self {
props,
link,
client: Client::default(),
}
}

fn update(&mut self, msg: Self::Message) -> ShouldRender {
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> ShouldRender {
let client = &mut self.client;
match msg {
Msg::UpdateFirstName(value) => {
Expand All @@ -51,27 +45,19 @@ impl Component for AddClientForm {
true
}
Msg::Add => {
self.props.on_add.emit(std::mem::take(client));
ctx.props().on_add.emit(std::mem::take(client));
true
}
Msg::Abort => {
self.props.on_abort.emit(());
ctx.props().on_abort.emit(());
false
}
}
}

fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props == props {
false
} else {
self.props = props;
true
}
}

fn view(&self) -> Html {
let Self { link, client, .. } = self;
fn view(&self, ctx: &Context<Self>) -> Html {
let link = ctx.link();
let Self { client, .. } = self;
html! {
<>
<div class="names">
Expand Down
Loading