Merge branch 'main' into axum-0.6
This commit is contained in:
commit
58abe55d7b
|
@ -11,7 +11,7 @@ serde = { version = "1", features = ["derive"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
console_log = "0.2"
|
console_log = "0.2"
|
||||||
console_error_panic_hook = "0.1.7"
|
console_error_panic_hook = "0.1.7"
|
||||||
|
gloo-timers = { version = "0.2", features = ["futures"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wasm-bindgen-test = "0.3.0"
|
wasm-bindgen-test = "0.3.0"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use gloo_timers::future::TimeoutFuture;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -9,6 +10,10 @@ pub struct Cat {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_cats(count: u32) -> Result<Vec<String>, ()> {
|
async fn fetch_cats(count: u32) -> Result<Vec<String>, ()> {
|
||||||
|
// artificial delay
|
||||||
|
// the cat API is too fast to show the transition
|
||||||
|
TimeoutFuture::new(500).await;
|
||||||
|
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
let res = reqwasm::http::Request::get(&format!(
|
let res = reqwasm::http::Request::get(&format!(
|
||||||
"https://api.thecatapi.com/v1/images/search?limit={}",
|
"https://api.thecatapi.com/v1/images/search?limit={}",
|
||||||
|
@ -32,8 +37,9 @@ async fn fetch_cats(count: u32) -> Result<Vec<String>, ()> {
|
||||||
pub fn fetch_example(cx: Scope) -> web_sys::Element {
|
pub fn fetch_example(cx: Scope) -> web_sys::Element {
|
||||||
let (cat_count, set_cat_count) = create_signal::<u32>(cx, 1);
|
let (cat_count, set_cat_count) = create_signal::<u32>(cx, 1);
|
||||||
let cats = create_resource(cx, cat_count, |count| fetch_cats(count));
|
let cats = create_resource(cx, cat_count, |count| fetch_cats(count));
|
||||||
|
let (pending, set_pending) = create_signal(cx, false);
|
||||||
|
|
||||||
view! { cx,
|
view! { cx,
|
||||||
<div>
|
<div>
|
||||||
<label>
|
<label>
|
||||||
"How many cats would you like?"
|
"How many cats would you like?"
|
||||||
|
@ -45,16 +51,22 @@ pub fn fetch_example(cx: Scope) -> web_sys::Element {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
{move || pending().then(|| view! { cx, <p>"Loading more cats..."</p> })}
|
||||||
<div>
|
<div>
|
||||||
<Suspense fallback={"Loading (Suspense Fallback)...".to_string()}>
|
// <Transition/> holds the previous value while new async data is being loaded
|
||||||
|
// Switch the <Transition/> to <Suspense/> to fall back to "Loading..." every time
|
||||||
|
<Transition
|
||||||
|
fallback={"Loading (Suspense Fallback)...".to_string()}
|
||||||
|
set_pending
|
||||||
|
>
|
||||||
{move || {
|
{move || {
|
||||||
cats.read().map(|data| match data {
|
cats.read().map(|data| match data {
|
||||||
Err(_) => view! { cx, <pre>"Error"</pre> },
|
Err(_) => view! { cx, <pre>"Error"</pre> },
|
||||||
Ok(cats) => view! { cx,
|
Ok(cats) => view! { cx,
|
||||||
<div>{
|
<div>{
|
||||||
cats.iter()
|
cats.iter()
|
||||||
.map(|src| {
|
.map(|src| {
|
||||||
view! { cx,
|
view! { cx,
|
||||||
<img src={src}/>
|
<img src={src}/>
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -64,7 +76,7 @@ pub fn fetch_example(cx: Scope) -> web_sys::Element {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</Suspense>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,10 @@ pub fn Stories(cx: Scope) -> Element {
|
||||||
api::fetch_api::<Vec<api::Story>>(cx, &api::story(&path)).await
|
api::fetch_api::<Vec<api::Story>>(cx, &api::story(&path)).await
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
let (pending, set_pending) = create_signal(cx, false);
|
||||||
|
|
||||||
let hide_more_link = move || stories.read().unwrap_or(None).unwrap_or_default().len() < 28;
|
let hide_more_link =
|
||||||
|
move || pending() || stories.read().unwrap_or(None).unwrap_or_default().len() < 28;
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
cx,
|
cx,
|
||||||
|
@ -76,7 +78,10 @@ pub fn Stories(cx: Scope) -> Element {
|
||||||
</div>
|
</div>
|
||||||
<main class="news-list">
|
<main class="news-list">
|
||||||
<div>
|
<div>
|
||||||
<Suspense fallback=view! { cx, <p>"Loading..."</p> }>
|
<Transition
|
||||||
|
fallback=view! { cx, <p>"Loading..."</p> }
|
||||||
|
set_pending
|
||||||
|
>
|
||||||
{move || match stories.read() {
|
{move || match stories.read() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(None) => Some(view! { cx, <p>"Error loading stories."</p> }),
|
Some(None) => Some(view! { cx, <p>"Error loading stories."</p> }),
|
||||||
|
@ -94,7 +99,7 @@ pub fn Stories(cx: Scope) -> Element {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
</Suspense>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -143,7 +143,7 @@ pub fn Settings(_cx: Scope) -> Element {
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>"Name"</legend>
|
<legend>"Name"</legend>
|
||||||
<input type="text" name="first_name" placeholder="First"/>
|
<input type="text" name="first_name" placeholder="First"/>
|
||||||
<input type="text" name="first_name" placeholder="Last"/>
|
<input type="text" name="last_name" placeholder="Last"/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<pre>"This page is just a placeholder."</pre>
|
<pre>"This page is just a placeholder."</pre>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -45,6 +45,13 @@ pub async fn handle_server_fns(
|
||||||
body: Bytes,
|
body: Bytes,
|
||||||
// req: Request<Body>,
|
// req: Request<Body>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
|
// Axum Path extractor doesn't remove the first slash from the path, while Actix does
|
||||||
|
let fn_name: String = match fn_name.strip_prefix("/") {
|
||||||
|
Some(path) => path.to_string(),
|
||||||
|
None => fn_name,
|
||||||
|
};
|
||||||
|
println!("Body: {:#?}", &body);
|
||||||
|
|
||||||
let (tx, rx) = futures::channel::oneshot::channel();
|
let (tx, rx) = futures::channel::oneshot::channel();
|
||||||
std::thread::spawn({
|
std::thread::spawn({
|
||||||
move || {
|
move || {
|
||||||
|
|
|
@ -12,6 +12,7 @@ leptos_dom = { path = "../leptos_dom", default-features = false, version = "0.0.
|
||||||
leptos_macro = { path = "../leptos_macro", default-features = false, version = "0.0.19" }
|
leptos_macro = { path = "../leptos_macro", default-features = false, version = "0.0.19" }
|
||||||
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.19" }
|
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.19" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
typed-builder = "0.11"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
leptos = { path = "../leptos", default-features = false, version = "0.0" }
|
leptos = { path = "../leptos", default-features = false, version = "0.0" }
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
mod for_component;
|
mod for_component;
|
||||||
mod map;
|
mod map;
|
||||||
mod suspense;
|
mod suspense;
|
||||||
|
mod transition;
|
||||||
|
|
||||||
pub use for_component::*;
|
pub use for_component::*;
|
||||||
pub use map::*;
|
pub use map::*;
|
||||||
pub use suspense::*;
|
pub use suspense::*;
|
||||||
|
pub use transition::*;
|
||||||
|
|
||||||
/// Describes the properties of a component. This is typically generated by the `Prop` derive macro
|
/// Describes the properties of a component. This is typically generated by the `Prop` derive macro
|
||||||
/// as part of the `#[component]` macro.
|
/// as part of the `#[component]` macro.
|
||||||
|
|
|
@ -20,7 +20,10 @@ where
|
||||||
|
|
||||||
/// If any [Resource](leptos_reactive::Resource)s are read in the `children` of this
|
/// If any [Resource](leptos_reactive::Resource)s are read in the `children` of this
|
||||||
/// component, it will show the `fallback` while they are loading. Once all are resolved,
|
/// component, it will show the `fallback` while they are loading. Once all are resolved,
|
||||||
/// it will render the `children`.
|
/// it will render the `children`. If data begin loading again, falls back to `fallback` again.
|
||||||
|
///
|
||||||
|
/// If you’d rather continue displaying the previous `children` while loading new data, see
|
||||||
|
/// [`Transition`](crate::Transition).
|
||||||
///
|
///
|
||||||
/// Note that the `children` will be rendered initially (in order to capture the fact that
|
/// Note that the `children` will be rendered initially (in order to capture the fact that
|
||||||
/// those resources are read under the suspense), so you cannot assume that resources have
|
/// those resources are read under the suspense), so you cannot assume that resources have
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
use leptos_dom::{Child, IntoChild};
|
||||||
|
use leptos_reactive::{provide_context, Scope, SignalSetter, SuspenseContext};
|
||||||
|
use typed_builder::TypedBuilder;
|
||||||
|
|
||||||
|
/// Props for the [Suspense](crate::Suspense) component, which shows a fallback
|
||||||
|
/// while [Resource](leptos_reactive::Resource)s are being read.
|
||||||
|
#[derive(TypedBuilder)]
|
||||||
|
pub struct TransitionProps<F, E, G>
|
||||||
|
where
|
||||||
|
F: IntoChild + Clone,
|
||||||
|
E: IntoChild,
|
||||||
|
G: Fn() -> E,
|
||||||
|
{
|
||||||
|
/// Will be displayed while resources are pending.
|
||||||
|
pub fallback: F,
|
||||||
|
/// A function that will be called when the component transitions into or out of
|
||||||
|
/// the `pending` state, with its argument indicating whether it is pending (`true`)
|
||||||
|
/// or not pending (`false`).
|
||||||
|
#[builder(default, setter(strip_option, into))]
|
||||||
|
pub set_pending: Option<SignalSetter<bool>>,
|
||||||
|
/// Will be displayed once all resources have resolved.
|
||||||
|
pub children: Box<dyn Fn() -> Vec<G>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If any [Resource](leptos_reactive::Resource)s are read in the `children` of this
|
||||||
|
/// component, it will show the `fallback` while they are loading. Once all are resolved,
|
||||||
|
/// it will render the `children`. Unlike [`Suspense`](crate::Suspense), this will not fall
|
||||||
|
/// back to the `fallback` state if there are further changes after the initial load.
|
||||||
|
///
|
||||||
|
/// Note that the `children` will be rendered initially (in order to capture the fact that
|
||||||
|
/// those resources are read under the suspense), so you cannot assume that resources have
|
||||||
|
/// `Some` value in `children`.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use leptos_reactive::*;
|
||||||
|
/// # use leptos_core::*;
|
||||||
|
/// # use leptos_macro::*;
|
||||||
|
/// # use leptos_dom::*; use leptos::*;
|
||||||
|
/// # run_scope(create_runtime(), |cx| {
|
||||||
|
/// # if cfg!(not(any(feature = "csr", feature = "hydrate", feature = "ssr"))) {
|
||||||
|
/// async fn fetch_cats(how_many: u32) -> Result<Vec<String>, ()> { Ok(vec![]) }
|
||||||
|
///
|
||||||
|
/// let (cat_count, set_cat_count) = create_signal::<u32>(cx, 1);
|
||||||
|
/// let (pending, set_pending) = create_signal(cx, false);
|
||||||
|
///
|
||||||
|
/// let cats = create_resource(cx, cat_count, |count| fetch_cats(count));
|
||||||
|
///
|
||||||
|
/// view! { cx,
|
||||||
|
/// <div>
|
||||||
|
/// <Transition
|
||||||
|
/// fallback={"Loading...".to_string()}
|
||||||
|
/// set_pending=set_pending
|
||||||
|
/// >
|
||||||
|
/// {move || {
|
||||||
|
/// cats.read().map(|data| match data {
|
||||||
|
/// Err(_) => view! { cx, <pre>"Error"</pre> },
|
||||||
|
/// Ok(cats) => view! { cx,
|
||||||
|
/// <div>{
|
||||||
|
/// cats.iter()
|
||||||
|
/// .map(|src| {
|
||||||
|
/// view! { cx,
|
||||||
|
/// <img src={src}/>
|
||||||
|
/// }
|
||||||
|
/// })
|
||||||
|
/// .collect::<Vec<_>>()
|
||||||
|
/// }</div>
|
||||||
|
/// },
|
||||||
|
/// })
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// </Transition>
|
||||||
|
/// </div>
|
||||||
|
/// };
|
||||||
|
/// # }
|
||||||
|
/// # });
|
||||||
|
/// ```
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn Transition<F, E, G>(cx: Scope, props: TransitionProps<F, E, G>) -> impl Fn() -> Child
|
||||||
|
where
|
||||||
|
F: IntoChild + Clone,
|
||||||
|
E: IntoChild,
|
||||||
|
G: Fn() -> E + 'static,
|
||||||
|
{
|
||||||
|
let context = SuspenseContext::new(cx);
|
||||||
|
|
||||||
|
// provide this SuspenseContext to any resources below it
|
||||||
|
provide_context(cx, context);
|
||||||
|
|
||||||
|
let child = (props.children)().swap_remove(0);
|
||||||
|
|
||||||
|
render_transition(cx, context, props.fallback, child, props.set_pending)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "csr", feature = "hydrate"))]
|
||||||
|
fn render_transition<'a, F, E, G>(
|
||||||
|
cx: Scope,
|
||||||
|
context: SuspenseContext,
|
||||||
|
fallback: F,
|
||||||
|
child: G,
|
||||||
|
set_pending: Option<SignalSetter<bool>>,
|
||||||
|
) -> impl Fn() -> Child
|
||||||
|
where
|
||||||
|
F: IntoChild + Clone,
|
||||||
|
E: IntoChild,
|
||||||
|
G: Fn() -> E,
|
||||||
|
{
|
||||||
|
use std::cell::{Cell, RefCell};
|
||||||
|
|
||||||
|
let has_rendered_once = Cell::new(false);
|
||||||
|
let prev_child = RefCell::new(Child::Null);
|
||||||
|
|
||||||
|
move || {
|
||||||
|
if context.ready() {
|
||||||
|
has_rendered_once.set(true);
|
||||||
|
let current_child = (child)().into_child(cx);
|
||||||
|
*prev_child.borrow_mut() = current_child.clone();
|
||||||
|
if let Some(pending) = &set_pending {
|
||||||
|
pending.set(false);
|
||||||
|
}
|
||||||
|
current_child
|
||||||
|
} else if has_rendered_once.get() {
|
||||||
|
if let Some(pending) = &set_pending {
|
||||||
|
pending.set(true);
|
||||||
|
}
|
||||||
|
prev_child.borrow().clone()
|
||||||
|
} else {
|
||||||
|
if let Some(pending) = &set_pending {
|
||||||
|
pending.set(true);
|
||||||
|
}
|
||||||
|
let fallback = fallback.clone().into_child(cx);
|
||||||
|
*prev_child.borrow_mut() = fallback.clone();
|
||||||
|
fallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(feature = "csr", feature = "hydrate")))]
|
||||||
|
fn render_transition<'a, F, E, G>(
|
||||||
|
cx: Scope,
|
||||||
|
context: SuspenseContext,
|
||||||
|
fallback: F,
|
||||||
|
orig_child: G,
|
||||||
|
set_pending: Option<SignalSetter<bool>>,
|
||||||
|
) -> impl Fn() -> Child
|
||||||
|
where
|
||||||
|
F: IntoChild + Clone,
|
||||||
|
E: IntoChild,
|
||||||
|
G: Fn() -> E + 'static,
|
||||||
|
{
|
||||||
|
use leptos_dom::IntoAttribute;
|
||||||
|
use leptos_macro::view;
|
||||||
|
|
||||||
|
_ = set_pending;
|
||||||
|
|
||||||
|
let initial = {
|
||||||
|
// run the child; we'll probably throw this away, but it will register resource reads
|
||||||
|
let mut child = orig_child().into_child(cx);
|
||||||
|
while let Child::Fn(f) = child {
|
||||||
|
child = (f.borrow_mut())();
|
||||||
|
}
|
||||||
|
|
||||||
|
// no resources were read under this, so just return the child
|
||||||
|
if context.pending_resources.get() == 0 {
|
||||||
|
child
|
||||||
|
}
|
||||||
|
// show the fallback, but also prepare to stream HTML
|
||||||
|
else {
|
||||||
|
let key = cx.current_fragment_key();
|
||||||
|
cx.register_suspense(context, &key, move || {
|
||||||
|
orig_child().into_child(cx).as_child_string()
|
||||||
|
});
|
||||||
|
|
||||||
|
// return the fallback for now, wrapped in fragment identifer
|
||||||
|
Child::Node(view! { cx, <div data-fragment-id=key>{fallback.into_child(cx)}</div> })
|
||||||
|
}
|
||||||
|
};
|
||||||
|
move || initial.clone()
|
||||||
|
}
|
|
@ -46,7 +46,10 @@ pub fn server_macro_impl(args: proc_macro::TokenStream, s: TokenStream2) -> Resu
|
||||||
if #[cfg(not(feature = "stable"))] {
|
if #[cfg(not(feature = "stable"))] {
|
||||||
use proc_macro::Span;
|
use proc_macro::Span;
|
||||||
let span = Span::call_site();
|
let span = Span::call_site();
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
let url = format!("{}/{}", span.source_file().path().to_string_lossy(), fn_name_as_str).replace("/", "-");
|
let url = format!("{}/{}", span.source_file().path().to_string_lossy(), fn_name_as_str).replace("/", "-");
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let url = format!("{}/{}", span.source_file().path().to_string_lossy(), fn_name_as_str).replace("\\", "-");
|
||||||
} else {
|
} else {
|
||||||
let url = fn_name_as_str;
|
let url = fn_name_as_str;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,7 @@ mod selector;
|
||||||
mod serialization;
|
mod serialization;
|
||||||
mod signal;
|
mod signal;
|
||||||
mod signal_wrappers_read;
|
mod signal_wrappers_read;
|
||||||
|
mod signal_wrappers_write;
|
||||||
mod spawn;
|
mod spawn;
|
||||||
mod suspense;
|
mod suspense;
|
||||||
|
|
||||||
|
@ -91,6 +92,7 @@ pub use selector::*;
|
||||||
pub use serialization::*;
|
pub use serialization::*;
|
||||||
pub use signal::*;
|
pub use signal::*;
|
||||||
pub use signal_wrappers_read::*;
|
pub use signal_wrappers_read::*;
|
||||||
|
pub use signal_wrappers_write::*;
|
||||||
pub use spawn::*;
|
pub use spawn::*;
|
||||||
pub use suspense::*;
|
pub use suspense::*;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::{Memo, ReadSignal, RwSignal, Scope, UntrackedGettableSignal};
|
use crate::{RwSignal, Scope, WriteSignal};
|
||||||
|
|
||||||
/// A wrapper for any kind of settable reactive signal: a [WriteSignal](crate::WriteSignal),
|
/// A wrapper for any kind of settable reactive signal: a [WriteSignal](crate::WriteSignal),
|
||||||
/// [RwSignal](crate::RwSignal), or closure that receives a value and sets a signal depending
|
/// [RwSignal](crate::RwSignal), or closure that receives a value and sets a signal depending
|
||||||
|
@ -14,13 +14,13 @@ use crate::{Memo, ReadSignal, RwSignal, Scope, UntrackedGettableSignal};
|
||||||
/// # use leptos_reactive::*;
|
/// # use leptos_reactive::*;
|
||||||
/// # create_scope(create_runtime(), |cx| {
|
/// # create_scope(create_runtime(), |cx| {
|
||||||
/// let (count, set_count) = create_signal(cx, 2);
|
/// let (count, set_count) = create_signal(cx, 2);
|
||||||
/// let set_double_input = SignalSetter::map(cx, |n| set_count(n * 2));
|
/// let set_double_input = SignalSetter::map(cx, move |n| set_count(n * 2));
|
||||||
///
|
///
|
||||||
/// // this function takes any kind of signal setter
|
/// // this function takes any kind of signal setter
|
||||||
/// fn set_to_4(setter: &SignalSetter<i32>) -> bool {
|
/// fn set_to_4(setter: &SignalSetter<i32>) {
|
||||||
/// // ✅ calling the signal sets the value
|
/// // ✅ calling the signal sets the value
|
||||||
/// // it is a shorthand for arg.set()
|
/// // it is a shorthand for arg.set()
|
||||||
/// setter(4)
|
/// setter(4);
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// set_to_4(&set_count.into());
|
/// set_to_4(&set_count.into());
|
||||||
|
@ -44,10 +44,10 @@ where
|
||||||
/// # use leptos_reactive::*;
|
/// # use leptos_reactive::*;
|
||||||
/// # create_scope(create_runtime(), |cx| {
|
/// # create_scope(create_runtime(), |cx| {
|
||||||
/// let (count, set_count) = create_signal(cx, 2);
|
/// let (count, set_count) = create_signal(cx, 2);
|
||||||
/// let double_count = SignalSetter::map(cx, move |n| set_count(n * 2));
|
/// let set_double_count = SignalSetter::map(cx, move |n| set_count(n * 2));
|
||||||
///
|
///
|
||||||
/// // this function takes any kind of signal setter
|
/// // this function takes any kind of signal setter
|
||||||
/// fn set_to_4(setter: &SignalSetter<i32>) -> bool {
|
/// fn set_to_4(setter: &SignalSetter<i32>) {
|
||||||
/// // ✅ calling the signal sets the value
|
/// // ✅ calling the signal sets the value
|
||||||
/// // it is a shorthand for arg.set()
|
/// // it is a shorthand for arg.set()
|
||||||
/// setter(4)
|
/// setter(4)
|
||||||
|
@ -55,7 +55,7 @@ where
|
||||||
///
|
///
|
||||||
/// set_to_4(&set_count.into());
|
/// set_to_4(&set_count.into());
|
||||||
/// assert_eq!(count(), 4);
|
/// assert_eq!(count(), 4);
|
||||||
/// set_to_4(&set_double_input);
|
/// set_to_4(&set_double_count);
|
||||||
/// assert_eq!(count(), 8);
|
/// assert_eq!(count(), 8);
|
||||||
/// # });
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -69,24 +69,24 @@ where
|
||||||
/// # use leptos_reactive::*;
|
/// # use leptos_reactive::*;
|
||||||
/// # create_scope(create_runtime(), |cx| {
|
/// # create_scope(create_runtime(), |cx| {
|
||||||
/// let (count, set_count) = create_signal(cx, 2);
|
/// let (count, set_count) = create_signal(cx, 2);
|
||||||
/// let double_count = SignalSetter::map(cx, move |n| set_count(n * 2));
|
/// let set_double_count = SignalSetter::map(cx, move |n| set_count(n * 2));
|
||||||
///
|
///
|
||||||
/// // this function takes any kind of signal setter
|
/// // this function takes any kind of signal setter
|
||||||
/// fn set_to_4(setter: &SignalSetter<i32>) -> bool {
|
/// fn set_to_4(setter: &SignalSetter<i32>) {
|
||||||
/// // ✅ calling the signal sets the value
|
/// // ✅ calling the signal sets the value
|
||||||
/// // it is a shorthand for arg.set()
|
/// // it is a shorthand for arg.set()
|
||||||
/// setter(4)
|
/// setter(4);
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// set_to_4(&set_count.into());
|
/// set_to_4(&set_count.into());
|
||||||
/// assert_eq!(count(), 4);
|
/// assert_eq!(count(), 4);
|
||||||
/// set_to_4(&set_double_input);
|
/// set_to_4(&set_double_count);
|
||||||
/// assert_eq!(count(), 8);
|
/// assert_eq!(count(), 8);
|
||||||
/// # });
|
/// # });
|
||||||
pub fn set(&self, value: T) {
|
pub fn set(&self, value: T) {
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
SignalSetterTypes::Write(s) => s.set(value),
|
SignalSetterTypes::Write(s) => s.set(value),
|
||||||
SignalSetterTypes::Wrapped(_, s) => s(value),
|
SignalSetterTypes::Mapped(_, s) => s(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,8 +108,8 @@ enum SignalSetterTypes<T>
|
||||||
where
|
where
|
||||||
T: 'static,
|
T: 'static,
|
||||||
{
|
{
|
||||||
Write(WriteSignalSetter<T>),
|
Write(WriteSignal<T>),
|
||||||
Mapped(Scope, Rc<dyn FnOnce(T)>),
|
Mapped(Scope, Rc<dyn Fn(T)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> std::fmt::Debug for SignalSetterTypes<T>
|
impl<T> std::fmt::Debug for SignalSetterTypes<T>
|
||||||
|
@ -118,9 +118,8 @@ where
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::ReadSignal(arg0) => f.debug_tuple("ReadSignal").field(arg0).finish(),
|
Self::Write(arg0) => f.debug_tuple("WriteSignal").field(arg0).finish(),
|
||||||
Self::Memo(arg0) => f.debug_tuple("Memo").field(arg0).finish(),
|
Self::Mapped(_, _) => f.debug_tuple("Mapped").finish(),
|
||||||
Self::DerivedSignal(_, _) => f.debug_tuple("DerivedSignal").finish(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,9 +130,8 @@ where
|
||||||
{
|
{
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Self::ReadSignal(l0), Self::ReadSignal(r0)) => l0 == r0,
|
(Self::Write(l0), Self::Write(r0)) => l0 == r0,
|
||||||
(Self::Memo(l0), Self::Memo(r0)) => l0 == r0,
|
(Self::Mapped(_, l0), Self::Mapped(_, r0)) => std::ptr::eq(l0, r0),
|
||||||
(Self::DerivedSignal(_, l0), Self::DerivedSignal(_, r0)) => std::ptr::eq(l0, r0),
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue