Update parent-child example

This commit is contained in:
Greg Johnston 2022-12-18 17:12:06 -05:00
parent c635adb426
commit fc8921445e

View file

@ -7,23 +7,21 @@ use web_sys::MouseEvent;
// for the child component to write into and the parent to read
// 2) <ButtonB/>: passing a closure as one of the child component props, for
// the child component to call
// 3) <ButtonC/>: adding a simple event listener on the child component itself
// 4) <ButtonD/>: providing a context that is used in the component (rather than prop drilling)
// 4) <ButtonC/>: providing a context that is used in the component (rather than prop drilling)
#[derive(Copy, Clone)]
struct SmallcapsContext(WriteSignal<bool>);
#[component]
pub fn App(cx: Scope) -> Element {
pub fn App(cx: Scope) -> impl IntoView {
// just some signals to toggle three classes on our <p>
let (red, set_red) = create_signal(cx, false);
let (right, set_right) = create_signal(cx, false);
let (italics, set_italics) = create_signal(cx, false);
let (smallcaps, set_smallcaps) = create_signal(cx, false);
// the newtype pattern isn't *necessary* here but is a good practice
// it avoids confusion with other possible future `WriteSignal<bool>` contexts
// and makes it easier to refer to it in ButtonD
// and makes it easier to refer to it in ButtonC
provide_context(cx, SmallcapsContext(set_smallcaps));
view! {
@ -33,7 +31,6 @@ pub fn App(cx: Scope) -> Element {
// class: attributes take F: Fn() => bool, and these signals all implement Fn()
class:red=red
class:right=right
class:italics=italics
class:smallcaps=smallcaps
>
"Lorem ipsum sit dolor amet."
@ -45,18 +42,19 @@ pub fn App(cx: Scope) -> Element {
// Button B: pass a closure
<ButtonB on_click=move |_| set_right.update(|value| *value = !*value)/>
// Button C: components that return an Element, like elements, can take on: event handler attributes
<ButtonC on:click=move |_| set_italics.update(|value| *value = !*value)/>
// Button D gets its setter from context rather than props
<ButtonD/>
<ButtonC/>
</main>
}
}
// Button A receives a signal setter and updates the signal itself
/// Button A receives a signal setter and updates the signal itself
#[component]
pub fn ButtonA(cx: Scope, setter: WriteSignal<bool>) -> Element {
pub fn ButtonA(
cx: Scope,
/// Signal that will be toggled when the button is clicked.
setter: WriteSignal<bool>
) -> impl IntoView {
view! {
cx,
<button
@ -67,9 +65,13 @@ pub fn ButtonA(cx: Scope, setter: WriteSignal<bool>) -> Element {
}
}
// Button B receives a closure
/// Button B receives a closure
#[component]
pub fn ButtonB<F>(cx: Scope, on_click: F) -> Element
pub fn ButtonB<F>(
cx: Scope,
/// Callback that will be invoked when the button is clicked.
on_click: F
) -> impl IntoView
where
F: Fn(MouseEvent) + 'static,
{
@ -95,22 +97,10 @@ where
// if Rust ever had named function arguments we could drop this requirement
}
// Button C will have its event listener added by the parent
// This is just a way of encapsulating whatever markup you need for the button
/// Button D is very similar to Button A, but instead of passing the setter as a prop
/// we get it from the context
#[component]
pub fn ButtonC(cx: Scope) -> Element {
view! {
cx,
<button>
"Toggle Italics"
</button>
}
}
// Button D is very similar to Button A, but instead of passing the setter as a prop
// we get it from the context
#[component]
pub fn ButtonD(cx: Scope) -> Element {
pub fn ButtonC(cx: Scope) -> impl IntoView {
let setter = use_context::<SmallcapsContext>(cx).unwrap().0;
view! {