change: migrate to nightly and csr features rather than stable and default-features = false (#1227)

This commit is contained in:
Greg Johnston 2023-06-26 21:12:14 -04:00 committed by GitHub
parent f5cfe4e8a2
commit ee7dbafc85
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
78 changed files with 430 additions and 483 deletions

View file

@ -16,10 +16,10 @@ Please copy and paste the Leptos dependencies and features from your `Cargo.toml
For example:
```toml
leptos = { version = "0.3", default-features = false, features = ["serde"] }
leptos = { version = "0.3", features = ["serde"] }
leptos_axum = { version = "0.3", optional = true }
leptos_meta = { version = "0.3", default-features = false }
leptos_router = { version = "0.3", default-features = false }
leptos_meta = { version = "0.3"}
leptos_router = { version = "0.3"}
```
**To Reproduce**

View file

@ -29,18 +29,18 @@ exclude = ["benchmarks", "examples"]
version = "0.3.0"
[workspace.dependencies]
leptos = { path = "./leptos", default-features = false, version = "0.3.0" }
leptos_dom = { path = "./leptos_dom", default-features = false, version = "0.3.0" }
leptos = { path = "./leptos", version = "0.3.0" }
leptos_dom = { path = "./leptos_dom", version = "0.3.0" }
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.3.0" }
leptos_macro = { path = "./leptos_macro", default-features = false, version = "0.3.0" }
leptos_reactive = { path = "./leptos_reactive", default-features = false, version = "0.3.0" }
leptos_server = { path = "./leptos_server", default-features = false, version = "0.3.0" }
server_fn = { path = "./server_fn", default-features = false, version = "0.3.0" }
server_fn_macro = { path = "./server_fn_macro", default-features = false, version = "0.3.0" }
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", default-features = false, version = "0.3.0" }
leptos_config = { path = "./leptos_config", default-features = false, version = "0.3.0" }
leptos_macro = { path = "./leptos_macro", version = "0.3.0" }
leptos_reactive = { path = "./leptos_reactive", version = "0.3.0" }
leptos_server = { path = "./leptos_server", version = "0.3.0" }
server_fn = { path = "./server_fn", version = "0.3.0" }
server_fn_macro = { path = "./server_fn_macro", version = "0.3.0" }
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.3.0" }
leptos_config = { path = "./leptos_config", version = "0.3.0" }
leptos_router = { path = "./router", version = "0.3.0" }
leptos_meta = { path = "./meta", default-features = false, version = "0.3.0" }
leptos_meta = { path = "./meta", version = "0.3.0" }
leptos_integration_utils = { path = "./integrations/utils", version = "0.3.0" }
[profile.release]

View file

@ -68,7 +68,7 @@ Here are some resources for learning more about Leptos:
## `nightly` Note
Most of the examples assume youre using `nightly` version of Rust. For this, you can either set your toolchain globally or on per-project basis.
Most of the examples assume youre using `nightly` version of Rust and the `nightly` feature of Leptos. To use `nightly` Rust, you can either set your toolchain globally or on per-project basis.
To set `nightly` as a default toolchain for all projects (and add the ability to compile Rust to WebAssembly, if you havent already):
@ -86,13 +86,7 @@ channel = "nightly"
targets = ["wasm32-unknown-unknown"]
```
If youre on `stable`, note the following:
1. You need to enable the `"stable"` flag in `Cargo.toml`: `leptos = { version = "0.2", features = ["stable"] }`
2. `nightly` enables the function call syntax for accessing and setting signals. If youre using `stable`,
youll just call `.get()`, `.set()`, or `.update()` manually. Check out the
[`counters_stable` example](https://github.com/leptos-rs/leptos/blob/main/examples/counters_stable/src/main.rs)
for examples of the correct API.
The `nightly` feature enables the function call syntax for accessing and setting signals, as opposed to `.get()` and `.set()`. This leads to a consistent mental model in which accessing a reactive value of any kind (a signal, memo, or derived signal) is always represented as a function call. This is only possible with nightly Rust and the `nightly` feature.
## `cargo-leptos`

View file

@ -5,7 +5,7 @@ edition = "2021"
[dependencies]
l021 = { package = "leptos", version = "0.2.1" }
leptos = { path = "../leptos", default-features = false, features = ["ssr"] }
leptos = { path = "../leptos", features = ["ssr"] }
sycamore = { version = "0.8", features = ["ssr"] }
yew = { git = "https://github.com/yewstack/yew", features = ["ssr"] }
tokio-test = "0.4"

View file

@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos" }
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
console_log = "1"
log = "0.4"
console_error_panic_hook = "0.1.7"

View file

@ -19,19 +19,17 @@ console_error_panic_hook = "0.1"
futures = "0.3"
cfg-if = "1"
lazy_static = "1"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos = { path = "../../leptos" }
leptos_actix = { path = "../../integrations/actix", optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
leptos_meta = { path = "../../meta" }
leptos_router = { path = "../../router" }
log = "0.4"
gloo-net = { git = "https://github.com/rustwasm/gloo" }
wasm-bindgen = "=0.2.86"
serde = { version = "1", features = ["derive"] }
[features]
default = []
default = ["nightly"]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [
"dep:actix-files",
@ -41,10 +39,10 @@ ssr = [
"leptos_meta/ssr",
"leptos_router/ssr",
]
stable = ["leptos/stable", "leptos_router/stable"]
nightly = ["leptos/nightly", "leptos_router/nightly"]
[package.metadata.cargo-all-features]
denylist = ["actix-files", "actix-web", "leptos_actix", "stable"]
denylist = ["actix-files", "actix-web", "leptos_actix", "nightly"]
skip_feature_sets = [["ssr", "hydrate"]]
[package.metadata.leptos]

View file

@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos", features = ["stable"] }
leptos = { path = "../../leptos", features = ["csr"] }
console_log = "1"
log = "0.4"
console_error_panic_hook = "0.1.7"

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos" }
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
log = "0.4"
console_log = "1"
console_error_panic_hook = "0.1.7"

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos", features = ["stable"] }
leptos = { path = "../../leptos", features = ["csr"] }
log = "0.4"
console_log = "1"
console_error_panic_hook = "0.1.7"

View file

@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos" }
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
console_log = "1"
log = "0.4"
console_error_panic_hook = "0.1.7"

View file

@ -10,12 +10,10 @@ crate-type = ["cdylib", "rlib"]
console_log = "1.0.0"
console_error_panic_hook = "0.1.7"
cfg-if = "1.0.0"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_axum = { path = "../../integrations/axum", default-features = false, optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_axum = { path = "../../integrations/axum", optional = true }
leptos_meta = { path = "../../meta" }
leptos_router = { path = "../../router" }
log = "0.4.17"
serde = { version = "1", features = ["derive"] }
simple_logger = "4.0.0"

View file

@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos" }
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
reqwasm = "0.5"
serde = { version = "1", features = ["derive"] }
log = "0.4"

View file

@ -4,5 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos" }
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
gtk = { version = "0.5.0", package = "gtk4" }

View file

@ -16,12 +16,10 @@ actix-web = { version = "4", optional = true, features = ["macros"] }
console_log = "1"
console_error_panic_hook = "0.1"
cfg-if = "1"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_meta = { path = "../../meta", default-features = false }
leptos_actix = { path = "../../integrations/actix", default-features = false, optional = true }
leptos_router = { path = "../../router", default-features = false }
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos_actix = { path = "../../integrations/actix", optional = true }
leptos_router = { path = "../../router", features = ["nightly"] }
log = "0.4"
serde = { version = "1", features = ["derive"] }
gloo-net = { version = "0.2", features = ["http"] }

View file

@ -14,12 +14,10 @@ lto = true
console_log = "1.0.0"
console_error_panic_hook = "0.1.7"
cfg-if = "1.0.0"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_axum = { path = "../../integrations/axum", optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos_router = { path = "../../router", features = ["nightly"] }
log = "0.4.17"
simple_logger = "4.0.0"
serde = { version = "1.0.148", features = ["derive"] }

View file

@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos", features=["template_macro"] }
leptos = { path = "../../leptos", features = ["csr", "nightly", "template_macro"] }
console_log = "1"
log = "0.4"
# used in rand, but we need to enable js feature

View file

@ -11,12 +11,10 @@ axum = { version = "0.6.18", optional = true }
console_error_panic_hook = "0.1.7"
console_log = "1"
cfg-if = "1"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_meta = { path = "../../meta", default-features = false }
leptos_axum = { path = "../../integrations/axum", default-features = false, optional = true }
leptos_router = { path = "../../router", default-features = false }
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos_axum = { path = "../../integrations/axum", optional = true }
leptos_router = { path = "../../router", features = ["nightly"] }
log = "0.4.17"
simple_logger = "4"
tokio = { version = "1.28.1", optional = true }

View file

@ -6,6 +6,6 @@ codegen-units = 1
lto = true
[patch.crates-io]
leptos = { path = "../../leptos" }
leptos_router = { path = "../../router" }
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_router = { path = "../../router", features = ["nightly"] }
api-boundary = { path = "api-boundary" }

View file

@ -7,8 +7,9 @@ publish = false
[dependencies]
api-boundary = "*"
leptos = { version = "0.2.0-alpha2", features = ["stable"] }
leptos_router = { version = "0.2.0-alpha2", features = ["stable", "csr"] }
leptos = { path = "../../../leptos", features = ["csr"] }
leptos_meta = { path = "../../../meta", features = ["csr"] }
leptos_router = { path = "../../../router", features = ["csr"] }
log = "0.4"
console_error_panic_hook = "0.1"

View file

@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos" }
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
console_log = "1"
log = "0.4"
console_error_panic_hook = "0.1.7"

View file

@ -10,12 +10,12 @@ lto = true
[dependencies]
console_log = "1"
log = "0.4"
leptos = { path = "../../leptos" }
leptos_router = { path = "../../router", features = ["csr"] }
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
leptos_router = { path = "../../router", features = ["csr", "nightly"] }
serde = { version = "1", features = ["derive"] }
futures = "0.3"
console_error_panic_hook = "0.1.7"
leptos_meta = { path = "../../meta", features = ["csr"] }
leptos_meta = { path = "../../meta", features = ["csr", "nightly"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.0"

View file

@ -13,12 +13,10 @@ rand = { version = "0.8.5", features = ["min_const_gen"], optional = true }
console_error_panic_hook = "0.1.7"
futures = "0.3.25"
cfg-if = "1.0.0"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_meta = { path = "../../meta", default-features = false }
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos_axum = { path = "../../integrations/axum", optional = true }
leptos_router = { path = "../../router", default-features = false }
leptos_router = { path = "../../router", features = ["nightly"] }
log = "0.4.17"
simple_logger = "4.0.0"
serde = { version = "1.0.148", features = ["derive"] }

View file

@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos" }
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
console_log = "1"
log = "0.4"
console_error_panic_hook = "0.1.7"

View file

@ -13,12 +13,10 @@ console_error_panic_hook = "0.1"
console_log = "1"
cfg-if = "1"
lazy_static = "1"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_meta = { path = "../../meta", default-features = false }
leptos_actix = { path = "../../integrations/actix", default-features = false, optional = true }
leptos_router = { path = "../../router", default-features = false }
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos_actix = { path = "../../integrations/actix", optional = true }
leptos_router = { path = "../../router", features = ["nightly"] }
log = "0.4"
serde = { version = "1", features = ["derive"] }
thiserror = "1"

View file

@ -11,12 +11,10 @@ console_error_panic_hook = "0.1"
console_log = "1"
cfg-if = "1"
lazy_static = "1"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_meta = { path = "../../meta", default-features = false }
leptos_axum = { path = "../../integrations/axum", default-features = false, optional = true }
leptos_router = { path = "../../router", default-features = false }
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos_axum = { path = "../../integrations/axum", optional = true }
leptos_router = { path = "../../router", features = ["nightly"] }
log = "0.4"
serde = { version = "1", features = ["derive"] }
thiserror = "1"

View file

@ -10,12 +10,10 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_actix = { path = "../../integrations/actix", optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos_router = { path = "../../router", features = ["nightly"] }
gloo-net = { version = "0.2", features = ["http"] }
log = "0.4"
cfg-if = "1.0"

View file

@ -4,12 +4,9 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { version = "0.2", features = [
"serde",
"csr",
] }
leptos_meta = { version = "0.2", features = ["csr"] }
leptos_router = { version = "0.2", features = ["csr"] }
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
leptos_meta = { path = "../../meta", features = ["csr", "nightly"] }
leptos_router = { path = "../../router", features = ["csr", "nightly"] }
log = "0.4"
gloo-net = { version = "0.2", features = ["http"] }

View file

@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos" }
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
console_log = "1"
log = "0.4"
console_error_panic_hook = "0.1.7"

View file

@ -16,12 +16,10 @@ console_error_panic_hook = "0.1.7"
serde = { version = "1.0.152", features = ["derive"] }
futures = "0.3.25"
cfg-if = "1.0.0"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_actix = { path = "../../integrations/actix", optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos_router = { path = "../../router", features = ["nightly"] }
log = "0.4.17"
simple_logger = "4.0.0"
gloo = { git = "https://github.com/rustwasm/gloo" }
@ -32,7 +30,6 @@ sqlx = { version = "0.6.2", features = [
wasm-bindgen = "0.2"
[features]
default = ["ssr"]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [
"dep:actix-files",

View file

@ -11,12 +11,10 @@ console_log = "1.0.0"
console_error_panic_hook = "0.1.7"
futures = "0.3.25"
cfg-if = "1.0.0"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_axum = { path = "../../integrations/axum", default-features = false, optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
leptos = { path = "../../leptos", features = ["nightly"] }
leptos_axum = { path = "../../integrations/axum", optional = true }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos_router = { path = "../../router", features = ["nightly"] }
log = "0.4.17"
simple_logger = "4.0.0"
serde = { version = "1", features = ["derive"] }
@ -33,8 +31,6 @@ thiserror = "1.0.38"
wasm-bindgen = "0.2"
[features]
default = ["csr"]
csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [
"dep:axum",

View file

@ -11,13 +11,11 @@ console_log = "1.0.0"
console_error_panic_hook = "0.1.7"
futures = "0.3.25"
cfg-if = "1.0.0"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_viz = { path = "../../integrations/viz", default-features = false, optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
leptos_reactive = { path = "../../leptos_reactive", default-features = false }
leptos = { path = "../../leptos" }
leptos_viz = { path = "../../integrations/viz", optional = true }
leptos_meta = { path = "../../meta", features = ["nightly"] }
leptos_router = { path = "../../router", features = ["nightly"] }
leptos_reactive = { path = "../../leptos_reactive", features = ["nightly"] }
log = "0.4.17"
simple_logger = "4.0.0"
serde = { version = "1", features = ["derive"] }
@ -32,7 +30,6 @@ thiserror = "1.0.38"
wasm-bindgen = "0.2"
[features]
default = ["csr"]
csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [

View file

@ -8,7 +8,7 @@ codegen-units = 1
lto = true
[dependencies]
leptos = { path = "../../leptos", default-features = false }
leptos = { path = "../../leptos", features = ["nightly"] }
log = "0.4"
console_log = "1"
console_error_panic_hook = "0.1.7"

View file

@ -13,19 +13,19 @@ cfg-if = "1"
leptos_dom = { workspace = true }
leptos_macro = { workspace = true }
leptos_reactive = { workspace = true }
leptos_server = { workspace = true, default-features = false }
leptos_server = { workspace = true}
leptos_config = { workspace = true }
tracing = "0.1"
typed-builder = "0.14"
server_fn = { workspace = true, default-features = false }
server_fn = { workspace = true}
web-sys = { version = "0.3.63", optional = true }
wasm-bindgen = { version = "0.2", optional = true }
[dev-dependencies]
leptos = { path = ".", default-features = false }
leptos = { path = "."}
[features]
default = ["csr", "serde"]
default = ["serde"]
template_macro = ["leptos_dom/web", "web-sys", "wasm-bindgen"]
csr = [
"leptos_dom/web",
@ -47,11 +47,11 @@ ssr = [
"leptos_reactive/ssr",
"leptos_server/ssr",
]
stable = [
"leptos_dom/stable",
"leptos_macro/stable",
"leptos_reactive/stable",
"leptos_server/stable",
nightly = [
"leptos_dom/nightly",
"leptos_macro/nightly",
"leptos_reactive/nightly",
"leptos_server/nightly",
]
serde = ["leptos_reactive/serde"]
serde-lite = ["leptos_reactive/serde-lite"]
@ -60,7 +60,7 @@ rkyv = ["leptos_reactive/rkyv"]
tracing = ["leptos_macro/tracing"]
[package.metadata.cargo-all-features]
denylist = ["stable", "tracing", "template_macro", "rustls", "default-tls", "web-sys", "wasm-bindgen"]
denylist = ["nightly", "tracing", "template_macro", "rustls", "default-tls", "web-sys", "wasm-bindgen"]
skip_feature_sets = [
[
"csr",

View file

@ -16,14 +16,14 @@ use leptos_reactive::{
/// # use leptos_dom::*; use leptos::*;
/// # run_scope(create_runtime(), |cx| {
/// let (value, set_value) = create_signal(cx, Ok(0));
/// let on_input = move |ev| set_value(event_target_value(&ev).parse::<i32>());
/// let on_input = move |ev| set_value.set(event_target_value(&ev).parse::<i32>());
///
/// view! { cx,
/// <input type="text" on:input=on_input/>
/// <ErrorBoundary
/// fallback=move |_, _| view! { cx, <p class="error">"Enter a valid number."</p>}
/// >
/// <p>"Value is: " {value}</p>
/// <p>"Value is: " {move || value.get()}</p>
/// </ErrorBoundary>
/// }
/// # });

View file

@ -26,7 +26,7 @@ use std::hash::Hash;
/// <div>
/// <For
/// // a function that returns the items we're iterating over; a signal is fine
/// each=counters
/// each=move || counters.get()
/// // a unique key for each item
/// key=|counter| counter.id
/// // renders each item to a view

View file

@ -16,14 +16,6 @@
//! Join us on our [Discord Channel](https://discord.gg/v38Eef6sWG) to see what the community is building.
//! Explore our [Examples](https://github.com/leptos-rs/leptos/tree/main/examples) to see Leptos in action.
//!
//! # `nightly` Note
//! Most of the examples assume youre using `nightly` Rust. If youre on stable, note the following:
//! 1. You need to enable the `"stable"` flag in `Cargo.toml`: `leptos = { version = "0.0", features = ["stable"] }`
//! 2. `nightly` enables the function call syntax for accessing and setting signals. If youre using `stable`,
//! youll just call `.get()`, `.set()`, or `.update()` manually. Check out the
//! [`counters_stable` example](https://github.com/leptos-rs/leptos/blob/main/examples/counters_stable/src/main.rs)
//! for examples of the correct API.
//!
//! # Learning by Example
//!
//! If you want to see what Leptos is capable of, check out
@ -84,12 +76,10 @@
//! - **Server Functions**: the [server](crate::leptos_server) macro, [create_action], and [create_server_action]
//!
//! # Feature Flags
//! - `csr` (*Default*) Client-side rendering: Generate DOM nodes in the browser
//! - `nightly`: On `nightly` Rust, enables the function-call syntax for signal getters and setters.
//! - `csr` Client-side rendering: Generate DOM nodes in the browser
//! - `ssr` Server-side rendering: Generate an HTML string (typically on the server)
//! - `hydrate` Hydration: use this to add interactivity to an SSRed Leptos app
//! - `stable` By default, Leptos requires `nightly` Rust, which is what allows the ergonomics
//! of calling signals as functions. If you need to use `stable`, you will need to call `.get()`
//! and `.set()` manually.
//! - `serde` (*Default*) In SSR/hydrate mode, uses [serde](https://docs.rs/serde/latest/serde/) to serialize resources and send them
//! from the server to the client.
//! - `serde-lite` In SSR/hydrate mode, uses [serde-lite](https://docs.rs/serde-lite/latest/serde_lite/) to serialize resources and send them
@ -122,7 +112,7 @@
//! <div>
//! <button on:click=clear>"Clear"</button>
//! <button on:click=decrement>"-1"</button>
//! <span>"Value: " {move || value().to_string()} "!"</span>
//! <span>"Value: " {move || value.get().to_string()} "!"</span>
//! <button on:click=increment>"+1"</button>
//! </div>
//! }

View file

@ -21,7 +21,7 @@ use std::{cell::RefCell, rc::Rc};
///
/// view! { cx,
/// <Show
/// when=move || value() < 5
/// when=move || value.get() < 5
/// fallback=|cx| view! { cx, "Big number!" }
/// >
/// "Small number!"

View file

@ -21,7 +21,7 @@ use std::rc::Rc;
///
/// 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, move || cat_count.get(), |count| fetch_cats(count));
///
/// view! { cx,
/// <div>

View file

@ -32,7 +32,8 @@ use std::{
/// 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));
/// let cats =
/// create_resource(cx, move || cat_count.get(), |count| fetch_cats(count));
///
/// view! { cx,
/// <div>

View file

@ -12,9 +12,9 @@ actix-web = { version = "4", optional = true, features = ["macros"] }
console_error_panic_hook = "0.1"
console_log = "1"
cfg-if = "1"
leptos = { path = "../../..", default-features = false, features = ["serde"] }
leptos = { path = "../../..", features = ["serde"] }
leptos_actix = { path = "../../../../integrations/actix", optional = true }
leptos_router = { path = "../../../../router", default-features = false }
leptos_router = { path = "../../../../router"}
log = "0.4"
simple_logger = "4"
wasm-bindgen = "0.2.87"

View file

@ -159,8 +159,8 @@ features = [
default = []
web = ["leptos_reactive/csr"]
ssr = ["leptos_reactive/ssr"]
stable = ["leptos_reactive/stable"]
nightly = ["leptos_reactive/nightly"]
[package.metadata.cargo-all-features]
denylist = ["stable"]
denylist = ["nightly"]
skip_feature_sets = [["web", "ssr"]]

View file

@ -7,7 +7,7 @@ edition = "2021"
crate-type = ["cdylib", "rlib"]
[dependencies]
leptos = { path = "../../../leptos", default-features = false }
leptos = { path = "../../../leptos", features = ["nightly"] }
actix-web = { version = "4", optional = true }
actix-files = { version = "0.6", optional = true }
wasm-bindgen = { version = "0.2", optional = true }

View file

@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
console_error_panic_hook = "0.1"
gloo = { version = "0.8", features = ["futures"] }
leptos = { path = "../../../leptos", features = ["tracing"] }
leptos = { path = "../../../leptos", features = ["nightly", "csr", "tracing"] }
tracing = "0.1"
tracing-subscriber = "0.3"
tracing-subscriber-wasm = "0.1"

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../leptos" }
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
console_log = "1"
log = "0.4"
console_error_panic_hook = "0.1.7"

View file

@ -1,7 +1,7 @@
#![deny(missing_docs)]
#![forbid(unsafe_code)]
#![cfg_attr(not(feature = "stable"), feature(fn_traits))]
#![cfg_attr(not(feature = "stable"), feature(unboxed_closures))]
#![cfg_attr(feature = "nightly", feature(fn_traits))]
#![cfg_attr(feature = "nightly", feature(unboxed_closures))]
//! The DOM implementation for `leptos`.
@ -1125,7 +1125,7 @@ viewable_primitive![
];
cfg_if! {
if #[cfg(not(feature = "stable"))] {
if #[cfg(feature = "nightly")] {
viewable_primitive! {
std::backtrace::Backtrace
}

View file

@ -154,7 +154,7 @@ impl<T: ElementDescriptor> Clone for NodeRef<T> {
impl<T: ElementDescriptor + 'static> Copy for NodeRef<T> {}
cfg_if::cfg_if! {
if #[cfg(not(feature = "stable"))] {
if #[cfg(feature = "nightly")] {
impl<T: Clone + ElementDescriptor + 'static> FnOnce<()> for NodeRef<T> {
type Output = Option<HtmlElement<T>>;

View file

@ -39,9 +39,9 @@ default = ["ssr"]
csr = []
hydrate = []
ssr = []
stable = ["server_fn_macro/stable"]
nightly = ["server_fn_macro/nightly"]
tracing = []
[package.metadata.cargo-all-features]
denylist = ["stable", "tracing"]
denylist = ["nightly", "tracing"]
skip_feature_sets = [["csr", "hydrate"], ["hydrate", "csr"], ["hydrate", "ssr"]]

View file

@ -1,4 +1,4 @@
#![cfg_attr(not(feature = "stable"), feature(proc_macro_span))]
#![cfg_attr(feature = "nightly", feature(proc_macro_span))]
#![forbid(unsafe_code)]
#[macro_use]
@ -94,7 +94,7 @@ mod template;
/// Attributes can take a wide variety of primitive types that can be converted to strings. They can also
/// take an `Option`, in which case `Some` sets the attribute and `None` removes the attribute.
///
/// ```rust
/// ```rust,ignore
/// # use leptos::*;
/// # run_scope(create_runtime(), |cx| {
/// # if !cfg!(any(feature = "csr", feature = "hydrate")) {
@ -102,11 +102,11 @@ mod template;
///
/// view! {
/// cx,
/// // ❌ not like this: `count()` returns an `i32`, not a function
/// <p>{count()}</p>
/// // ❌ not like this: `count.get()` returns an `i32`, not a function
/// <p>{count.get()}</p>
/// // ✅ this is good: Leptos sees the function and knows it's a dynamic value
/// <p>{move || count.get()}</p>
/// // 🔥 `count` is itself a function, so you can pass it directly (unless you're on `stable`)
/// // 🔥 with the `nightly` feature, `count` is a function, so `count` itself can be passed directly into the view
/// <p>{count}</p>
/// }
/// # ;
@ -147,9 +147,9 @@ mod template;
/// <input
/// type="text"
/// name="user_name"
/// value={name} // this only sets the default value!
/// prop:value={name} // here's how you update values. Sorry, I didnt invent the DOM.
/// on:click=move |ev| set_name(event_target_value(&ev)) // `event_target_value` is a useful little Leptos helper
/// value={move || name.get()} // this only sets the default value!
/// prop:value={move || name.get()} // here's how you update values. Sorry, I didnt invent the DOM.
/// on:click=move |ev| set_name.set(event_target_value(&ev)) // `event_target_value` is a useful little Leptos helper
/// />
/// }
/// # ;
@ -163,7 +163,7 @@ mod template;
/// # run_scope(create_runtime(), |cx| {
/// # if !cfg!(any(feature = "csr", feature = "hydrate")) {
/// let (count, set_count) = create_signal(cx, 2);
/// view! { cx, <div class:hidden-div={move || count() < 3}>"Now you see me, now you dont."</div> }
/// view! { cx, <div class:hidden-div={move || count.get() < 3}>"Now you see me, now you dont."</div> }
/// # ;
/// # }
/// # });
@ -176,7 +176,7 @@ mod template;
/// # if !cfg!(any(feature = "csr", feature = "hydrate")) {
/// let (count, set_count) = create_signal(cx, 2);
/// // `hidden-div-25` is invalid at the moment
/// view! { cx, <div class:hidden-div-25={move || count() < 3}>"Now you see me, now you dont."</div> }
/// view! { cx, <div class:hidden-div-25={move || count.get() < 3}>"Now you see me, now you dont."</div> }
/// # ;
/// # }
/// # });
@ -191,7 +191,7 @@ mod template;
/// // this allows you to use CSS frameworks that include complex class names
/// view! { cx,
/// <div
/// class=("is-[this_-_really]-necessary-42", move || count() < 3)
/// class=("is-[this_-_really]-necessary-42", move || count.get() < 3)
/// >
/// "Now you see me, now you dont."
/// </div>
@ -211,9 +211,9 @@ mod template;
/// view! { cx,
/// <div
/// style="position: absolute"
/// style:left=move || format!("{}px", x())
/// style:top=move || format!("{}px", y())
/// style=("background-color", move || format!("rgb({}, {}, 100)", x(), y()))
/// style:left=move || format!("{}px", x.get())
/// style:top=move || format!("{}px", y.get())
/// style=("background-color", move || format!("rgb({}, {}, 100)", x.get(), y.get()))
/// >
/// "Moves when coordinates change"
/// </div>
@ -285,7 +285,7 @@ mod template;
///
/// // create event handlers for our buttons
/// // note that `value` and `set_value` are `Copy`, so it's super easy to move them into closures
/// let clear = move |_ev| set_value(0);
/// let clear = move |_ev| set_value.set(0);
/// let decrement = move |_ev| set_value.update(|value| *value -= 1);
/// let increment = move |_ev| set_value.update(|value| *value += 1);
///
@ -295,7 +295,7 @@ mod template;
/// <div>
/// <button on:click=clear>"Clear"</button>
/// <button on:click=decrement>"-1"</button>
/// <span>"Value: " {move || value().to_string()} "!"</span>
/// <span>"Value: " {move || value.get().to_string()} "!"</span>
/// <button on:click=increment>"+1"</button>
/// </div>
/// }
@ -381,7 +381,7 @@ pub fn view(tokens: TokenStream) -> TokenStream {
fn normalized_call_site(site: proc_macro::Span) -> Option<String> {
cfg_if::cfg_if! {
if #[cfg(all(debug_assertions, not(feature = "stable")))] {
if #[cfg(all(debug_assertions, feature = "nightly"))] {
Some(leptos_hot_reload::span_to_stable_id(
site.source_file().path(),
site.into()
@ -467,7 +467,7 @@ pub fn template(tokens: TokenStream) -> TokenStream {
/// // return the user interface, which will be automatically updated
/// // when signal values change
/// view! { cx,
/// <p>"Your name is " {name} " and you are " {age} " years old."</p>
/// <p>"Your name is " {name} " and you are " {move || age.get()} " years old."</p>
/// }
/// }
///

View file

@ -68,14 +68,14 @@ hydrate = [
"dep:web-sys",
]
ssr = ["dep:tokio"]
stable = []
nightly = []
serde = []
serde-lite = ["dep:serde-lite"]
miniserde = ["dep:miniserde"]
rkyv = ["dep:rkyv", "dep:bytecheck"]
[package.metadata.cargo-all-features]
denylist = ["stable"]
denylist = ["nightly"]
skip_feature_sets = [
[
"csr",

View file

@ -29,20 +29,20 @@ use std::{any::Any, cell::RefCell, marker::PhantomData, rc::Rc};
/// // ✅ use effects to interact between reactive state and the outside world
/// create_effect(cx, move |_| {
/// // immediately prints "Value: 0" and subscribes to `a`
/// log::debug!("Value: {}", a());
/// log::debug!("Value: {}", a.get());
/// });
///
/// set_a(1);
/// set_a.set(1);
/// // ✅ because it's subscribed to `a`, the effect reruns and prints "Value: 1"
///
/// // ❌ don't use effects to synchronize state within the reactive system
/// create_effect(cx, move |_| {
/// // this technically works but can cause unnecessary re-renders
/// // and easily lead to problems like infinite loops
/// set_b(a() + 1);
/// set_b.set(a.get() + 1);
/// });
/// # if !cfg!(feature = "ssr") {
/// # assert_eq!(b(), 2);
/// # assert_eq!(b.get(), 2);
/// # }
/// # }).dispose();
/// ```
@ -88,19 +88,19 @@ where
/// // ✅ use effects to interact between reactive state and the outside world
/// create_isomorphic_effect(cx, move |_| {
/// // immediately prints "Value: 0" and subscribes to `a`
/// log::debug!("Value: {}", a());
/// log::debug!("Value: {}", a.get());
/// });
///
/// set_a(1);
/// set_a.set(1);
/// // ✅ because it's subscribed to `a`, the effect reruns and prints "Value: 1"
///
/// // ❌ don't use effects to synchronize state within the reactive system
/// create_isomorphic_effect(cx, move |_| {
/// // this technically works but can cause unnecessary re-renders
/// // and easily lead to problems like infinite loops
/// set_b(a() + 1);
/// set_b.set(a.get() + 1);
/// });
/// # assert_eq!(b(), 2);
/// # assert_eq!(b.get(), 2);
/// # }).dispose();
#[cfg_attr(
any(debug_assertions, feature="ssr"),

View file

@ -1,7 +1,7 @@
#![deny(missing_docs)]
#![cfg_attr(not(feature = "stable"), feature(fn_traits))]
#![cfg_attr(not(feature = "stable"), feature(unboxed_closures))]
#![cfg_attr(not(feature = "stable"), feature(type_name_of_val))]
#![cfg_attr(feature = "nightly", feature(fn_traits))]
#![cfg_attr(feature = "nightly", feature(unboxed_closures))]
#![cfg_attr(feature = "nightly", feature(type_name_of_val))]
//! The reactive system for the [Leptos](https://docs.rs/leptos/latest/leptos/) Web framework.
//!
@ -44,25 +44,28 @@
//! let (count, set_count) = create_signal(cx, 0);
//!
//! // calling the getter gets the value
//! assert_eq!(count(), 0);
//! // can be `count()` on nightly
//! assert_eq!(count.get(), 0);
//! // calling the setter sets the value
//! set_count(1);
//! // can be `set_count(1)` on nightly
//! set_count.set(1);
//! // or we can mutate it in place with update()
//! set_count.update(|n| *n += 1);
//!
//! // a derived signal: a plain closure that relies on the signal
//! // the closure will run whenever we *access* double_count()
//! let double_count = move || count() * 2;
//! let double_count = move || count.get() * 2;
//! assert_eq!(double_count(), 4);
//!
//! // a memo: subscribes to the signal
//! // the closure will run only when count changes
//! let memoized_triple_count = create_memo(cx, move |_| count() * 3);
//! assert_eq!(memoized_triple_count(), 6);
//! let memoized_triple_count = create_memo(cx, move |_| count.get() * 3);
//! // can be `memoized_triple_count()` on nightly
//! assert_eq!(memoized_triple_count.get(), 6);
//!
//! // this effect will run whenever count() changes
//! // this effect will run whenever `count` changes
//! create_effect(cx, move |_| {
//! println!("Count = {}", count());
//! println!("Count = {}", count.get());
//! });
//! });
//! ```

View file

@ -40,12 +40,12 @@ use std::{any::Any, cell::RefCell, fmt, marker::PhantomData, rc::Rc};
/// let (value, set_value) = create_signal(cx, 0);
///
/// // 🆗 we could create a derived signal with a simple function
/// let double_value = move || value() * 2;
/// set_value(2);
/// let double_value = move || value.get() * 2;
/// set_value.set(2);
/// assert_eq!(double_value(), 4);
///
/// // but imagine the computation is really expensive
/// let expensive = move || really_expensive_computation(value()); // lazy: doesn't run until called
/// let expensive = move || really_expensive_computation(value.get()); // lazy: doesn't run until called
/// create_effect(cx, move |_| {
/// // 🆗 run #1: calls `really_expensive_computation` the first time
/// log::debug!("expensive = {}", expensive());
@ -58,14 +58,15 @@ use std::{any::Any, cell::RefCell, fmt, marker::PhantomData, rc::Rc};
///
/// // instead, we create a memo
/// // 🆗 run #1: the calculation runs once immediately
/// let memoized = create_memo(cx, move |_| really_expensive_computation(value()));
/// let memoized = create_memo(cx, move |_| really_expensive_computation(value.get()));
/// create_effect(cx, move |_| {
/// // 🆗 reads the current value of the memo
/// log::debug!("memoized = {}", memoized());
/// // 🆗 reads the current value of the memo
/// // can be `memoized()` on nightly
/// log::debug!("memoized = {}", memoized.get());
/// });
/// create_effect(cx, move |_| {
/// // ✅ reads the current value **without re-running the calculation**
/// let value = memoized();
/// let value = memoized.get();
/// // do something else...
/// });
/// # }).dispose();
@ -131,12 +132,12 @@ where
/// let (value, set_value) = create_signal(cx, 0);
///
/// // 🆗 we could create a derived signal with a simple function
/// let double_value = move || value() * 2;
/// set_value(2);
/// let double_value = move || value.get() * 2;
/// set_value.set(2);
/// assert_eq!(double_value(), 4);
///
/// // but imagine the computation is really expensive
/// let expensive = move || really_expensive_computation(value()); // lazy: doesn't run until called
/// let expensive = move || really_expensive_computation(value.get()); // lazy: doesn't run until called
/// create_effect(cx, move |_| {
/// // 🆗 run #1: calls `really_expensive_computation` the first time
/// log::debug!("expensive = {}", expensive());
@ -149,14 +150,15 @@ where
///
/// // instead, we create a memo
/// // 🆗 run #1: the calculation runs once immediately
/// let memoized = create_memo(cx, move |_| really_expensive_computation(value()));
/// let memoized = create_memo(cx, move |_| really_expensive_computation(value.get()));
/// create_effect(cx, move |_| {
/// // 🆗 reads the current value of the memo
/// log::debug!("memoized = {}", memoized());
/// log::debug!("memoized = {}", memoized.get());
/// });
/// create_effect(cx, move |_| {
/// // ✅ reads the current value **without re-running the calculation**
/// let value = memoized();
/// // can be `memoized()` on nightly
/// let value = memoized.get();
/// // do something else...
/// });
/// # }).dispose();
@ -327,13 +329,14 @@ impl<T> SignalWithUntracked<T> for Memo<T> {
/// # use leptos_reactive::*;
/// # create_scope(create_runtime(), |cx| {
/// let (count, set_count) = create_signal(cx, 0);
/// let double_count = create_memo(cx, move |_| count() * 2);
/// let double_count = create_memo(cx, move |_| count.get() * 2);
///
/// assert_eq!(double_count.get(), 0);
/// set_count(1);
/// set_count.set(1);
///
/// // double_count() is shorthand for double_count.get()
/// assert_eq!(double_count(), 2);
/// // can be `double_count()` on nightly
/// // assert_eq!(double_count(), 2);
/// assert_eq!(double_count.get(), 2);
/// # }).dispose();
/// #
/// ```

View file

@ -51,7 +51,7 @@ use std::{
/// # // `csr`, `hydrate`, and `ssr` all have issues here
/// # // because we're not running in a browser or in Tokio. Let's just ignore it.
/// # if false {
/// let cats = create_resource(cx, how_many_cats, fetch_cat_picture_urls);
/// let cats = create_resource(cx, move || how_many_cats.get(), fetch_cat_picture_urls);
///
/// // when we read the signal, it contains either
/// // 1) None (if the Future isn't ready yet) or
@ -59,7 +59,7 @@ use std::{
/// assert_eq!(cats.read(cx), Some(vec!["1".to_string()]));
///
/// // when the signal's value changes, the `Resource` will generate and run a new `Future`
/// set_how_many_cats(2);
/// set_how_many_cats.set(2);
/// assert_eq!(cats.read(cx), Some(vec!["2".to_string()]));
/// # }
/// # }).dispose();
@ -696,7 +696,7 @@ impl<S, T> SignalSet<T> for Resource<S, T> {
/// # // `csr`, `hydrate`, and `ssr` all have issues here
/// # // because we're not running in a browser or in Tokio. Let's just ignore it.
/// # if false {
/// let cats = create_resource(cx, how_many_cats, fetch_cat_picture_urls);
/// let cats = create_resource(cx, move || how_many_cats.get(), fetch_cat_picture_urls);
///
/// // when we read the signal, it contains either
/// // 1) None (if the Future isn't ready yet) or
@ -704,7 +704,7 @@ impl<S, T> SignalSet<T> for Resource<S, T> {
/// assert_eq!(cats.read(cx), Some(vec!["1".to_string()]));
///
/// // when the signal's value changes, the `Resource` will generate and run a new `Future`
/// set_how_many_cats(2);
/// set_how_many_cats.set(2);
/// assert_eq!(cats.read(cx), Some(vec!["2".to_string()]));
/// # }
/// # }).dispose();

View file

@ -189,17 +189,17 @@ impl Scope {
/// let (b, set_b) = create_signal(cx, 0);
/// let c = create_memo(cx, move |_| {
/// // this memo will *only* update when `a` changes
/// a() + cx.untrack(move || b())
/// a.get() + cx.untrack(move || b.get())
/// });
///
/// assert_eq!(c(), 0);
/// set_a(1);
/// assert_eq!(c(), 1);
/// set_b(1);
/// assert_eq!(c.get(), 0);
/// set_a.set(1);
/// assert_eq!(c.get(), 1);
/// set_b.set(1);
/// // hasn't updated, because we untracked before reading b
/// assert_eq!(c(), 1);
/// set_a(2);
/// assert_eq!(c(), 3);
/// assert_eq!(c.get(), 1);
/// set_a.set(2);
/// assert_eq!(c.get(), 3);
///
/// # });
/// ```

View file

@ -19,7 +19,7 @@ use std::{cell::RefCell, collections::HashMap, hash::Hash, rc::Rc};
/// # use std::cell::RefCell;
/// # create_scope(create_runtime(), |cx| {
/// let (a, set_a) = create_signal(cx, 0);
/// let is_selected = create_selector(cx, a);
/// let is_selected = create_selector(cx, move || a.get());
/// let total_notifications = Rc::new(RefCell::new(0));
/// let not = Rc::clone(&total_notifications);
/// create_isomorphic_effect(cx, {
@ -33,13 +33,13 @@ use std::{cell::RefCell, collections::HashMap, hash::Hash, rc::Rc};
///
/// assert_eq!(is_selected(5), false);
/// assert_eq!(*total_notifications.borrow(), 0);
/// set_a(5);
/// set_a.set(5);
/// assert_eq!(is_selected(5), true);
/// assert_eq!(*total_notifications.borrow(), 1);
/// set_a(5);
/// set_a.set(5);
/// assert_eq!(is_selected(5), true);
/// assert_eq!(*total_notifications.borrow(), 1);
/// set_a(4);
/// set_a.set(4);
/// assert_eq!(is_selected(5), false);
/// # })
/// # .dispose()

View file

@ -23,7 +23,7 @@ use thiserror::Error;
macro_rules! impl_get_fn_traits {
($($ty:ident $(($method_name:ident))?),*) => {
$(
#[cfg(not(feature = "stable"))]
#[cfg(feature = "nightly")]
impl<T: Clone> FnOnce<()> for $ty<T> {
type Output = T;
@ -33,7 +33,7 @@ macro_rules! impl_get_fn_traits {
}
}
#[cfg(not(feature = "stable"))]
#[cfg(feature = "nightly")]
impl<T: Clone> FnMut<()> for $ty<T> {
#[inline(always)]
extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
@ -41,7 +41,7 @@ macro_rules! impl_get_fn_traits {
}
}
#[cfg(not(feature = "stable"))]
#[cfg(feature = "nightly")]
impl<T: Clone> Fn<()> for $ty<T> {
#[inline(always)]
extern "rust-call" fn call(&self, _args: ()) -> Self::Output {
@ -61,7 +61,7 @@ macro_rules! impl_get_fn_traits {
macro_rules! impl_set_fn_traits {
($($ty:ident $($method_name:ident)?),*) => {
$(
#[cfg(not(feature = "stable"))]
#[cfg(feature = "nightly")]
impl<T> FnOnce<(T,)> for $ty<T> {
type Output = ();
@ -71,7 +71,7 @@ macro_rules! impl_set_fn_traits {
}
}
#[cfg(not(feature = "stable"))]
#[cfg(feature = "nightly")]
impl<T> FnMut<(T,)> for $ty<T> {
#[inline(always)]
extern "rust-call" fn call_mut(&mut self, args: (T,)) -> Self::Output {
@ -79,7 +79,7 @@ macro_rules! impl_set_fn_traits {
}
}
#[cfg(not(feature = "stable"))]
#[cfg(feature = "nightly")]
impl<T> Fn<(T,)> for $ty<T> {
#[inline(always)]
extern "rust-call" fn call(&self, args: (T,)) -> Self::Output {
@ -290,24 +290,26 @@ pub trait SignalDispose {
/// let (count, set_count) = create_signal(cx, 0);
///
/// // ✅ calling the getter clones and returns the value
/// assert_eq!(count(), 0);
/// // this can be `count()` on nightly
/// assert_eq!(count.get(), 0);
///
/// // ✅ calling the setter sets the value
/// set_count(1);
/// assert_eq!(count(), 1);
/// // this can be `set_count(1)` on nightly
/// set_count.set(1);
/// assert_eq!(count.get(), 1);
///
/// // ❌ you could call the getter within the setter
/// // set_count(count() + 1);
/// // set_count.set(count.get() + 1);
///
/// // ✅ however it's more efficient to use .update() and mutate the value in place
/// set_count.update(|count: &mut i32| *count += 1);
/// assert_eq!(count(), 2);
/// assert_eq!(count.get(), 2);
///
/// // ✅ you can create "derived signals" with the same Fn() -> T interface
/// let double_count = move || count() * 2; // signals are `Copy` so you can `move` them anywhere
/// set_count(0);
/// // ✅ you can create "derived signals" with a Fn() -> T interface
/// let double_count = move || count.get() * 2; // signals are `Copy` so you can `move` them anywhere
/// set_count.set(0);
/// assert_eq!(double_count(), 0);
/// set_count(1);
/// set_count.set(1);
/// assert_eq!(double_count(), 2);
/// # }).dispose();
/// #
@ -447,24 +449,24 @@ pub fn create_signal_from_stream<T>(
/// let (count, set_count) = create_signal(cx, 0);
///
/// // ✅ calling the getter clones and returns the value
/// assert_eq!(count(), 0);
/// assert_eq!(count.get(), 0);
///
/// // ✅ calling the setter sets the value
/// set_count(1);
/// assert_eq!(count(), 1);
/// set_count.set(1); // `set_count(1)` on nightly
/// assert_eq!(count.get(), 1);
///
/// // ❌ you could call the getter within the setter
/// // set_count(count() + 1);
/// // set_count.set(count.get() + 1);
///
/// // ✅ however it's more efficient to use .update() and mutate the value in place
/// set_count.update(|count: &mut i32| *count += 1);
/// assert_eq!(count(), 2);
/// assert_eq!(count.get(), 2);
///
/// // ✅ you can create "derived signals" with the same Fn() -> T interface
/// let double_count = move || count() * 2; // signals are `Copy` so you can `move` them anywhere
/// set_count(0);
/// let double_count = move || count.get() * 2; // signals are `Copy` so you can `move` them anywhere
/// set_count.set(0);
/// assert_eq!(double_count(), 0);
/// set_count(1);
/// set_count.set(1);
/// assert_eq!(double_count(), 2);
/// # }).dispose();
/// #
@ -585,13 +587,13 @@ impl<T> SignalWithUntracked<T> for ReadSignal<T> {
/// let (name, set_name) = create_signal(cx, "Alice".to_string());
///
/// // ❌ unnecessarily clones the string
/// let first_char = move || name().chars().next().unwrap();
/// let first_char = move || name.get().chars().next().unwrap();
/// assert_eq!(first_char(), 'A');
///
/// // ✅ gets the first char without cloning the `String`
/// let first_char = move || name.with(|n| n.chars().next().unwrap());
/// assert_eq!(first_char(), 'A');
/// set_name("Bob".to_string());
/// set_name.set("Bob".to_string());
/// assert_eq!(first_char(), 'B');
/// # });
/// ```
@ -662,8 +664,8 @@ impl<T> SignalWith<T> for ReadSignal<T> {
///
/// assert_eq!(count.get(), 0);
///
/// // count() is shorthand for count.get()
/// assert_eq!(count(), 0);
/// // count() is shorthand for count.get() on `nightly`
/// // assert_eq!(count.get(), 0);
/// # });
/// ```
impl<T: Clone> SignalGet<T> for ReadSignal<T> {
@ -849,15 +851,16 @@ impl<T> Hash for ReadSignal<T> {
/// let (count, set_count) = create_signal(cx, 0);
///
/// // ✅ calling the setter sets the value
/// set_count(1);
/// assert_eq!(count(), 1);
/// // `set_count(1)` on nightly
/// set_count.set(1);
/// assert_eq!(count.get(), 1);
///
/// // ❌ you could call the getter within the setter
/// // set_count(count() + 1);
/// // set_count.set(count.get() + 1);
///
/// // ✅ however it's more efficient to use .update() and mutate the value in place
/// set_count.update(|count: &mut i32| *count += 1);
/// assert_eq!(count(), 2);
/// assert_eq!(count.get(), 2);
/// # }).dispose();
/// #
/// ```
@ -952,13 +955,13 @@ impl<T> SignalUpdateUntracked<T> for WriteSignal<T> {
/// let (count, set_count) = create_signal(cx, 0);
///
/// // notifies subscribers
/// set_count.update(|n| *n = 1); // it's easier just to call set_count(1), though!
/// assert_eq!(count(), 1);
/// set_count.update(|n| *n = 1); // it's easier just to call set_count.set(1), though!
/// assert_eq!(count.get(), 1);
///
/// // you can include arbitrary logic in this update function
/// // also notifies subscribers, even though the value hasn't changed
/// set_count.update(|n| if *n > 3 { *n += 1 });
/// assert_eq!(count(), 1);
/// assert_eq!(count.get(), 1);
/// # }).dispose();
/// ```
impl<T> SignalUpdate<T> for WriteSignal<T> {
@ -1012,13 +1015,13 @@ impl<T> SignalUpdate<T> for WriteSignal<T> {
/// let (count, set_count) = create_signal(cx, 0);
///
/// // notifies subscribers
/// set_count.update(|n| *n = 1); // it's easier just to call set_count(1), though!
/// assert_eq!(count(), 1);
/// set_count.update(|n| *n = 1); // it's easier just to call set_count.set(1), though!
/// assert_eq!(count.get(), 1);
///
/// // you can include arbitrary logic in this update function
/// // also notifies subscribers, even though the value hasn't changed
/// set_count.update(|n| if *n > 3 { *n += 1 });
/// assert_eq!(count(), 1);
/// assert_eq!(count.get(), 1);
/// # }).dispose();
/// ```
impl<T> SignalSet<T> for WriteSignal<T> {
@ -1113,14 +1116,14 @@ impl<T> Hash for WriteSignal<T> {
///
/// // ✅ set the value
/// count.set(1);
/// assert_eq!(count(), 1);
/// assert_eq!(count.get(), 1);
///
/// // ❌ you can call the getter within the setter
/// // count.set(count.get() + 1);
///
/// // ✅ however, it's more efficient to use .update() and mutate the value in place
/// count.update(|count: &mut i32| *count += 1);
/// assert_eq!(count(), 2);
/// assert_eq!(count.get(), 2);
/// # }).dispose();
/// #
/// ```
@ -1173,14 +1176,14 @@ pub fn create_rw_signal<T>(cx: Scope, value: T) -> RwSignal<T> {
///
/// // ✅ set the value
/// count.set(1);
/// assert_eq!(count(), 1);
/// assert_eq!(count.get(), 1);
///
/// // ❌ you can call the getter within the setter
/// // count.set(count.get() + 1);
///
/// // ✅ however, it's more efficient to use .update() and mutate the value in place
/// count.update(|count: &mut i32| *count += 1);
/// assert_eq!(count(), 2);
/// assert_eq!(count.get(), 2);
/// # }).dispose();
/// #
/// ```
@ -1413,7 +1416,7 @@ impl<T> SignalUpdateUntracked<T> for RwSignal<T> {
/// let name = create_rw_signal(cx, "Alice".to_string());
///
/// // ❌ unnecessarily clones the string
/// let first_char = move || name().chars().next().unwrap();
/// let first_char = move || name.get().chars().next().unwrap();
/// assert_eq!(first_char(), 'A');
///
/// // ✅ gets the first char without cloning the `String`
@ -1491,8 +1494,8 @@ impl<T> SignalWith<T> for RwSignal<T> {
///
/// assert_eq!(count.get(), 0);
///
/// // count() is shorthand for count.get()
/// assert_eq!(count(), 0);
/// // count() is shorthand for count.get() on `nightly`
/// // assert_eq!(count(), 0);
/// # }).dispose();
/// #
/// ```
@ -1563,8 +1566,8 @@ impl<T: Clone> SignalGet<T> for RwSignal<T> {
/// let count = create_rw_signal(cx, 0);
///
/// // notifies subscribers
/// count.update(|n| *n = 1); // it's easier just to call set_count(1), though!
/// assert_eq!(count(), 1);
/// count.update(|n| *n = 1); // it's easier just to call set_count.set(1), though!
/// assert_eq!(count.get(), 1);
///
/// // you can include arbitrary logic in this update function
/// // also notifies subscribers, even though the value hasn't changed
@ -1573,7 +1576,7 @@ impl<T: Clone> SignalGet<T> for RwSignal<T> {
/// *n += 1
/// }
/// });
/// assert_eq!(count(), 1);
/// assert_eq!(count.get(), 1);
/// # }).dispose();
/// ```
impl<T> SignalUpdate<T> for RwSignal<T> {
@ -1626,9 +1629,9 @@ impl<T> SignalUpdate<T> for RwSignal<T> {
/// # create_scope(create_runtime(), |cx| {
/// let count = create_rw_signal(cx, 0);
///
/// assert_eq!(count(), 0);
/// assert_eq!(count.get(), 0);
/// count.set(1);
/// assert_eq!(count(), 1);
/// assert_eq!(count.get(), 1);
/// # }).dispose();
/// ```
impl<T> SignalSet<T> for RwSignal<T> {
@ -1706,11 +1709,11 @@ impl<T> RwSignal<T> {
/// # create_scope(create_runtime(), |cx| {
/// let count = create_rw_signal(cx, 0);
/// let read_count = count.read_only();
/// assert_eq!(count(), 0);
/// assert_eq!(read_count(), 0);
/// assert_eq!(count.get(), 0);
/// assert_eq!(read_count.get(), 0);
/// count.set(1);
/// assert_eq!(count(), 1);
/// assert_eq!(read_count(), 1);
/// assert_eq!(count.get(), 1);
/// assert_eq!(read_count.get(), 1);
/// # }).dispose();
/// ```
#[cfg_attr(
@ -1746,9 +1749,9 @@ impl<T> RwSignal<T> {
/// # create_scope(create_runtime(), |cx| {
/// let count = create_rw_signal(cx, 0);
/// let set_count = count.write_only();
/// assert_eq!(count(), 0);
/// set_count(1);
/// assert_eq!(count(), 1);
/// assert_eq!(count.get(), 0);
/// set_count.set(1);
/// assert_eq!(count.get(), 1);
/// # }).dispose();
/// ```
#[cfg_attr(
@ -1781,11 +1784,11 @@ impl<T> RwSignal<T> {
/// # create_scope(create_runtime(), |cx| {
/// let count = create_rw_signal(cx, 0);
/// let (get_count, set_count) = count.split();
/// assert_eq!(count(), 0);
/// assert_eq!(get_count(), 0);
/// set_count(1);
/// assert_eq!(count(), 1);
/// assert_eq!(get_count(), 1);
/// assert_eq!(count.get(), 0);
/// assert_eq!(get_count.get(), 0);
/// set_count.set(1);
/// assert_eq!(count.get(), 1);
/// assert_eq!(get_count.get(), 1);
/// # }).dispose();
/// ```
#[cfg_attr(

View file

@ -45,14 +45,14 @@ where
/// # use leptos_reactive::*;
/// # create_scope(create_runtime(), |cx| {
/// let (count, set_count) = create_signal(cx, 2);
/// let double_count = Signal::derive(cx, move || count() * 2);
/// let memoized_double_count = create_memo(cx, move |_| count() * 2);
/// let double_count = Signal::derive(cx, move || count.get() * 2);
/// let memoized_double_count = create_memo(cx, move |_| count.get() * 2);
///
/// // this function takes any kind of wrapped signal
/// fn above_3(arg: &Signal<i32>) -> bool {
/// // ✅ calling the signal clones and returns the value
/// // it is a shorthand for arg.get()
/// arg() > 3
/// // can be `arg() > 3` on nightly
/// arg.get() > 3
/// }
///
/// assert_eq!(above_3(&count.into()), false);
@ -210,7 +210,7 @@ impl<T> SignalWithUntracked<T> for Signal<T> {
/// // this function takes any kind of wrapped signal
/// fn current_len_inefficient(arg: Signal<String>) -> usize {
/// // ❌ unnecessarily clones the string
/// arg().len()
/// arg.get().len()
/// }
///
/// fn current_len(arg: &Signal<String>) -> usize {
@ -222,9 +222,9 @@ impl<T> SignalWithUntracked<T> for Signal<T> {
/// assert_eq!(current_len(&name_upper), 5);
/// assert_eq!(current_len(&memoized_lower.into()), 5);
///
/// assert_eq!(name(), "Alice");
/// assert_eq!(name_upper(), "ALICE");
/// assert_eq!(memoized_lower(), "alice");
/// assert_eq!(name.get(), "Alice");
/// assert_eq!(name_upper.get(), "ALICE");
/// assert_eq!(memoized_lower.get(), "alice");
/// # });
/// ```
impl<T> SignalWith<T> for Signal<T> {
@ -276,8 +276,8 @@ impl<T> SignalWith<T> for Signal<T> {
/// # use leptos_reactive::*;
/// # create_scope(create_runtime(), |cx| {
/// let (count, set_count) = create_signal(cx, 2);
/// let double_count = Signal::derive(cx, move || count() * 2);
/// let memoized_double_count = create_memo(cx, move |_| count() * 2);
/// let double_count = Signal::derive(cx, move || count.get() * 2);
/// let memoized_double_count = create_memo(cx, move |_| count.get() * 2);
///
/// // this function takes any kind of wrapped signal
/// fn above_3(arg: &Signal<i32>) -> bool {
@ -342,7 +342,7 @@ where
/// # use leptos_reactive::*;
/// # create_scope(create_runtime(), |cx| {
/// let (count, set_count) = create_signal(cx, 2);
/// let double_count = Signal::derive(cx, move || count() * 2);
/// let double_count = Signal::derive(cx, move || count.get() * 2);
///
/// // this function takes any kind of wrapped signal
/// fn above_3(arg: &Signal<i32>) -> bool {
@ -499,15 +499,15 @@ impl<T> Eq for SignalTypes<T> where T: PartialEq {}
/// # use leptos_reactive::*;
/// # create_scope(create_runtime(), |cx| {
/// let (count, set_count) = create_signal(cx, 2);
/// let double_count = MaybeSignal::derive(cx, move || count() * 2);
/// let memoized_double_count = create_memo(cx, move |_| count() * 2);
/// let double_count = MaybeSignal::derive(cx, move || count.get() * 2);
/// let memoized_double_count = create_memo(cx, move |_| count.get() * 2);
/// let static_value = 5;
///
/// // this function takes either a reactive or non-reactive value
/// fn above_3(arg: &MaybeSignal<i32>) -> bool {
/// // ✅ calling the signal clones and returns the value
/// // it is a shorthand for arg.get()
/// arg() > 3
/// arg.get() > 3
/// }
///
/// assert_eq!(above_3(&static_value.into()), true);
@ -550,8 +550,8 @@ impl<T: Default> Default for MaybeSignal<T> {
/// # use leptos_reactive::*;
/// # create_scope(create_runtime(), |cx| {
/// let (count, set_count) = create_signal(cx, 2);
/// let double_count = MaybeSignal::derive(cx, move || count() * 2);
/// let memoized_double_count = create_memo(cx, move |_| count() * 2);
/// let double_count = MaybeSignal::derive(cx, move || count.get() * 2);
/// let memoized_double_count = create_memo(cx, move |_| count.get() * 2);
/// let static_value: MaybeSignal<i32> = 5.into();
///
/// // this function takes any kind of wrapped signal
@ -596,7 +596,7 @@ impl<T: Clone> SignalGet<T> for MaybeSignal<T> {
/// // this function takes any kind of wrapped signal
/// fn current_len_inefficient(arg: &MaybeSignal<String>) -> usize {
/// // ❌ unnecessarily clones the string
/// arg().len()
/// arg.get().len()
/// }
///
/// fn current_len(arg: &MaybeSignal<String>) -> usize {
@ -609,10 +609,10 @@ impl<T: Clone> SignalGet<T> for MaybeSignal<T> {
/// assert_eq!(current_len(&memoized_lower.into()), 5);
/// assert_eq!(current_len(&static_value), 3);
///
/// assert_eq!(name(), "Alice");
/// assert_eq!(name_upper(), "ALICE");
/// assert_eq!(memoized_lower(), "alice");
/// assert_eq!(static_value(), "Bob");
/// assert_eq!(name.get(), "Alice");
/// assert_eq!(name_upper.get(), "ALICE");
/// assert_eq!(memoized_lower.get(), "alice");
/// assert_eq!(static_value.get(), "Bob");
/// # });
/// ```
impl<T> SignalWith<T> for MaybeSignal<T> {
@ -709,7 +709,7 @@ where
/// # use leptos_reactive::*;
/// # create_scope(create_runtime(), |cx| {
/// let (count, set_count) = create_signal(cx, 2);
/// let double_count = Signal::derive(cx, move || count() * 2);
/// let double_count = Signal::derive(cx, move || count.get() * 2);
///
/// // this function takes any kind of wrapped signal
/// fn above_3(arg: &MaybeSignal<i32>) -> bool {

View file

@ -36,19 +36,19 @@ where
/// # use leptos_reactive::*;
/// # create_scope(create_runtime(), |cx| {
/// let (count, set_count) = create_signal(cx, 2);
/// let set_double_input = SignalSetter::map(cx, move |n| set_count(n * 2));
/// let set_double_input = SignalSetter::map(cx, move |n| set_count.set(n * 2));
///
/// // this function takes any kind of signal setter
/// fn set_to_4(setter: &SignalSetter<i32>) {
/// // ✅ calling the signal sets the value
/// // it is a shorthand for arg.set()
/// setter(4);
/// // can be `setter(4)` on nightly
/// setter.set(4);
/// }
///
/// set_to_4(&set_count.into());
/// assert_eq!(count(), 4);
/// assert_eq!(count.get(), 4);
/// set_to_4(&set_double_input);
/// assert_eq!(count(), 8);
/// assert_eq!(count.get(), 8);
/// # });
/// ```
#[derive(Debug, PartialEq, Eq)]
@ -121,19 +121,19 @@ where
/// # use leptos_reactive::*;
/// # create_scope(create_runtime(), |cx| {
/// let (count, set_count) = create_signal(cx, 2);
/// let set_double_count = SignalSetter::map(cx, move |n| set_count(n * 2));
/// let set_double_count = SignalSetter::map(cx, move |n| set_count.set(n * 2));
///
/// // this function takes any kind of signal setter
/// fn set_to_4(setter: &SignalSetter<i32>) {
/// // ✅ calling the signal sets the value
/// // it is a shorthand for arg.set()
/// setter(4)
/// // can be `setter(4)` on nightly
/// setter.set(4)
/// }
///
/// set_to_4(&set_count.into());
/// assert_eq!(count(), 4);
/// assert_eq!(count.get(), 4);
/// set_to_4(&set_double_count);
/// assert_eq!(count(), 8);
/// assert_eq!(count.get(), 8);
/// # });
/// ```
#[track_caller]
@ -164,19 +164,19 @@ where
/// # use leptos_reactive::*;
/// # create_scope(create_runtime(), |cx| {
/// let (count, set_count) = create_signal(cx, 2);
/// let set_double_count = SignalSetter::map(cx, move |n| set_count(n * 2));
/// let set_double_count = SignalSetter::map(cx, move |n| set_count.set(n * 2));
///
/// // this function takes any kind of signal setter
/// fn set_to_4(setter: &SignalSetter<i32>) {
/// // ✅ calling the signal sets the value
/// // it is a shorthand for arg.set()
/// setter(4);
/// // can be `setter(4)` on nightly
/// setter.set(4);
/// }
///
/// set_to_4(&set_count.into());
/// assert_eq!(count(), 4);
/// assert_eq!(count.get(), 4);
/// set_to_4(&set_double_count);
/// assert_eq!(count(), 8);
/// assert_eq!(count.get(), 8);
/// # });
#[cfg_attr(
any(debug_assertions, feature = "ssr"),

View file

@ -56,17 +56,17 @@ use crate::{
///
/// create_effect(cx, move |_| {
/// // note: in the browser, use leptos::log! instead
/// println!("name is {}", name());
/// println!("name is {}", name.get());
/// });
/// create_effect(cx, move |_| {
/// println!("count is {}", count());
/// println!("count is {}", count.get());
/// });
///
/// // setting count only causes count to log, not name
/// set_count(42);
/// set_count.set(42);
///
/// // setting name only causes name to log, not count
/// set_name("Bob".into());
/// set_name.set("Bob".into());
/// ```
pub fn create_slice<T, O, S>(
cx: Scope,

View file

@ -87,8 +87,8 @@ impl<T> StoredValue<T> {
///
/// // calling .get_value() clones and returns the value
/// assert_eq!(data.get_value().value, "a");
/// // there's a short-hand getter form
/// assert_eq!(data().value, "a");
/// // can be `data().value` on nightly
/// // assert_eq!(data().value, "a");
/// # });
/// ```
#[track_caller]

View file

@ -77,7 +77,8 @@ impl Trigger {
/// let o = output.clone();
/// let e = external_data.clone();
/// create_effect(cx, move |_| {
/// rerun_on_data(); // or rerun_on_data.track();
/// // can be `rerun_on_data()` on nightly
/// rerun_on_data.track();
/// write!(o.borrow_mut(), "{}", *e.borrow());
/// *e.borrow_mut() += 1;
/// });
@ -225,7 +226,7 @@ impl SignalSet<()> for Trigger {
}
}
#[cfg(not(feature = "stable"))]
#[cfg(feature = "nightly")]
impl FnOnce<()> for Trigger {
type Output = ();
@ -235,7 +236,7 @@ impl FnOnce<()> for Trigger {
}
}
#[cfg(not(feature = "stable"))]
#[cfg(feature = "nightly")]
impl FnMut<()> for Trigger {
#[inline(always)]
extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
@ -243,7 +244,7 @@ impl FnMut<()> for Trigger {
}
}
#[cfg(not(feature = "stable"))]
#[cfg(feature = "nightly")]
impl Fn<()> for Trigger {
#[inline(always)]
extern "rust-call" fn call(&self, _args: ()) -> Self::Output {

View file

@ -1,10 +1,8 @@
#[cfg(not(feature = "stable"))]
use leptos_reactive::{
create_isomorphic_effect, create_memo, create_runtime, create_rw_signal,
create_scope, create_signal, SignalSet,
create_scope, create_signal, SignalGet, SignalSet,
};
#[cfg(not(feature = "stable"))]
#[test]
fn effect_runs() {
use std::{cell::RefCell, rc::Rc};
@ -18,28 +16,27 @@ fn effect_runs() {
create_isomorphic_effect(cx, {
let b = b.clone();
move |_| {
let formatted = format!("Value is {}", a());
let formatted = format!("Value is {}", a.get());
*b.borrow_mut() = formatted;
}
});
assert_eq!(b.borrow().as_str(), "Value is -1");
set_a(1);
set_a.set(1);
assert_eq!(b.borrow().as_str(), "Value is 1");
})
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn effect_tracks_memo() {
use std::{cell::RefCell, rc::Rc};
create_scope(create_runtime(), |cx| {
let (a, set_a) = create_signal(cx, -1);
let b = create_memo(cx, move |_| format!("Value is {}", a()));
let b = create_memo(cx, move |_| format!("Value is {}", a.get()));
// simulate an arbitrary side effect
let c = Rc::new(RefCell::new(String::new()));
@ -47,22 +44,21 @@ fn effect_tracks_memo() {
create_isomorphic_effect(cx, {
let c = c.clone();
move |_| {
*c.borrow_mut() = b();
*c.borrow_mut() = b.get();
}
});
assert_eq!(b().as_str(), "Value is -1");
assert_eq!(b.get().as_str(), "Value is -1");
assert_eq!(c.borrow().as_str(), "Value is -1");
set_a(1);
set_a.set(1);
assert_eq!(b().as_str(), "Value is 1");
assert_eq!(b.get().as_str(), "Value is 1");
assert_eq!(c.borrow().as_str(), "Value is 1");
})
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn untrack_mutes_effect() {
use std::{cell::RefCell, rc::Rc};
@ -76,23 +72,23 @@ fn untrack_mutes_effect() {
create_isomorphic_effect(cx, {
let b = b.clone();
move |_| {
let formatted = format!("Value is {}", cx.untrack(a));
let formatted =
format!("Value is {}", cx.untrack(move || a.get()));
*b.borrow_mut() = formatted;
}
});
assert_eq!(a(), -1);
assert_eq!(a.get(), -1);
assert_eq!(b.borrow().as_str(), "Value is -1");
set_a(1);
set_a.set(1);
assert_eq!(a(), 1);
assert_eq!(a.get(), 1);
assert_eq!(b.borrow().as_str(), "Value is -1");
})
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn batching_actually_batches() {
use std::{cell::Cell, rc::Rc};
@ -107,8 +103,8 @@ fn batching_actually_batches() {
create_isomorphic_effect(cx, {
let count = count.clone();
move |_| {
_ = first_name();
_ = last_name();
_ = first_name.get();
_ = last_name.get();
count.set(count.get() + 1);
}

View file

@ -1,19 +1,14 @@
#[cfg(not(feature = "stable"))]
use leptos_reactive::{
create_memo, create_runtime, create_scope, create_signal,
};
use leptos_reactive::*;
#[cfg(not(feature = "stable"))]
#[test]
fn basic_memo() {
create_scope(create_runtime(), |cx| {
let a = create_memo(cx, |_| 5);
assert_eq!(a(), 5);
assert_eq!(a.get(), 5);
})
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn signal_with_untracked() {
use leptos_reactive::SignalWithUntracked;
@ -26,7 +21,6 @@ fn signal_with_untracked() {
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn signal_get_untracked() {
use leptos_reactive::SignalGetUntracked;
@ -39,45 +33,42 @@ fn signal_get_untracked() {
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn memo_with_computed_value() {
create_scope(create_runtime(), |cx| {
let (a, set_a) = create_signal(cx, 0);
let (b, set_b) = create_signal(cx, 0);
let c = create_memo(cx, move |_| a() + b());
assert_eq!(c(), 0);
set_a(5);
assert_eq!(c(), 5);
set_b(1);
assert_eq!(c(), 6);
let c = create_memo(cx, move |_| a.get() + b.get());
assert_eq!(c.get(), 0);
set_a.set(5);
assert_eq!(c.get(), 5);
set_b.set(1);
assert_eq!(c.get(), 6);
})
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn nested_memos() {
create_scope(create_runtime(), |cx| {
let (a, set_a) = create_signal(cx, 0); // 1
let (b, set_b) = create_signal(cx, 0); // 2
let c = create_memo(cx, move |_| a() + b()); // 3
let d = create_memo(cx, move |_| c() * 2); // 4
let e = create_memo(cx, move |_| d() + 1); // 5
assert_eq!(d(), 0);
set_a(5);
assert_eq!(e(), 11);
assert_eq!(d(), 10);
assert_eq!(c(), 5);
set_b(1);
assert_eq!(e(), 13);
assert_eq!(d(), 12);
assert_eq!(c(), 6);
let c = create_memo(cx, move |_| a.get() + b.get()); // 3
let d = create_memo(cx, move |_| c.get() * 2); // 4
let e = create_memo(cx, move |_| d.get() + 1); // 5
assert_eq!(d.get(), 0);
set_a.set(5);
assert_eq!(e.get(), 11);
assert_eq!(d.get(), 10);
assert_eq!(c.get(), 5);
set_b.set(1);
assert_eq!(e.get(), 13);
assert_eq!(d.get(), 12);
assert_eq!(c.get(), 6);
})
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn memo_runs_only_when_inputs_change() {
use std::{cell::Cell, rc::Rc};
@ -95,7 +86,7 @@ fn memo_runs_only_when_inputs_change() {
let call_count = call_count.clone();
move |_| {
call_count.set(call_count.get() + 1);
a() + b() + c()
a.get() + b.get() + c.get()
}
});
@ -103,24 +94,23 @@ fn memo_runs_only_when_inputs_change() {
assert_eq!(call_count.get(), 0);
// here we access the value a bunch of times
assert_eq!(c(), 0);
assert_eq!(c(), 0);
assert_eq!(c(), 0);
assert_eq!(c(), 0);
assert_eq!(c(), 0);
assert_eq!(c.get(), 0);
assert_eq!(c.get(), 0);
assert_eq!(c.get(), 0);
assert_eq!(c.get(), 0);
assert_eq!(c.get(), 0);
// we've still only called the memo calculation once
assert_eq!(call_count.get(), 1);
// and we only call it again when an input changes
set_a(1);
assert_eq!(c(), 1);
set_a.set(1);
assert_eq!(c.get(), 1);
assert_eq!(call_count.get(), 2);
})
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn diamond_problem() {
use std::{cell::Cell, rc::Rc};
@ -128,10 +118,10 @@ fn diamond_problem() {
create_scope(create_runtime(), |cx| {
let (name, set_name) = create_signal(cx, "Greg Johnston".to_string());
let first = create_memo(cx, move |_| {
name().split_whitespace().next().unwrap().to_string()
name.get().split_whitespace().next().unwrap().to_string()
});
let last = create_memo(cx, move |_| {
name().split_whitespace().nth(1).unwrap().to_string()
name.get().split_whitespace().nth(1).unwrap().to_string()
});
let combined_count = Rc::new(Cell::new(0));
@ -139,17 +129,17 @@ fn diamond_problem() {
let combined_count = Rc::clone(&combined_count);
move |_| {
combined_count.set(combined_count.get() + 1);
format!("{} {}", first(), last())
format!("{} {}", first.get(), last.get())
}
});
assert_eq!(first(), "Greg");
assert_eq!(last(), "Johnston");
assert_eq!(first.get(), "Greg");
assert_eq!(last.get(), "Johnston");
set_name("Will Smith".to_string());
assert_eq!(first(), "Will");
assert_eq!(last(), "Smith");
assert_eq!(combined(), "Will Smith");
set_name.set("Will Smith".to_string());
assert_eq!(first.get(), "Will");
assert_eq!(last.get(), "Smith");
assert_eq!(combined.get(), "Will Smith");
// should not have run the memo logic twice, even
// though both paths have been updated
assert_eq!(combined_count.get(), 1);
@ -157,7 +147,6 @@ fn diamond_problem() {
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn dynamic_dependencies() {
use leptos_reactive::create_isomorphic_effect;
@ -168,10 +157,10 @@ fn dynamic_dependencies() {
let (last, set_last) = create_signal(cx, "Johnston");
let (use_last, set_use_last) = create_signal(cx, true);
let name = create_memo(cx, move |_| {
if use_last() {
format!("{} {}", first(), last())
if use_last.get() {
format!("{} {}", first.get(), last.get())
} else {
first().to_string()
first.get().to_string()
}
});
@ -180,37 +169,37 @@ fn dynamic_dependencies() {
create_isomorphic_effect(cx, {
let combined_count = Rc::clone(&combined_count);
move |_| {
_ = name();
_ = name.get();
combined_count.set(combined_count.get() + 1);
}
});
assert_eq!(combined_count.get(), 1);
set_first("Bob");
assert_eq!(name(), "Bob Johnston");
set_first.set("Bob");
assert_eq!(name.get(), "Bob Johnston");
assert_eq!(combined_count.get(), 2);
set_last("Thompson");
set_last.set("Thompson");
assert_eq!(combined_count.get(), 3);
set_use_last(false);
set_use_last.set(false);
assert_eq!(name(), "Bob");
assert_eq!(name.get(), "Bob");
assert_eq!(combined_count.get(), 4);
assert_eq!(combined_count.get(), 4);
set_last("Jones");
set_last.set("Jones");
assert_eq!(combined_count.get(), 4);
set_last("Smith");
set_last.set("Smith");
assert_eq!(combined_count.get(), 4);
set_last("Stevens");
set_last.set("Stevens");
assert_eq!(combined_count.get(), 4);
set_use_last(true);
assert_eq!(name(), "Bob Stevens");
set_use_last.set(true);
assert_eq!(name.get(), "Bob Stevens");
assert_eq!(combined_count.get(), 5);
})
.dispose()

View file

@ -1,29 +1,26 @@
#[cfg(not(feature = "stable"))]
use leptos_reactive::{create_runtime, create_scope, create_signal};
use leptos_reactive::*;
#[cfg(not(feature = "stable"))]
#[test]
fn basic_signal() {
create_scope(create_runtime(), |cx| {
let (a, set_a) = create_signal(cx, 0);
assert_eq!(a(), 0);
set_a(5);
assert_eq!(a(), 5);
assert_eq!(a.get(), 0);
set_a.set(5);
assert_eq!(a.get(), 5);
})
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn derived_signals() {
create_scope(create_runtime(), |cx| {
let (a, set_a) = create_signal(cx, 0);
let (b, set_b) = create_signal(cx, 0);
let c = move || a() + b();
let c = move || a.get() + b.get();
assert_eq!(c(), 0);
set_a(5);
set_a.set(5);
assert_eq!(c(), 5);
set_b(1);
set_b.set(1);
assert_eq!(c(), 6);
})
.dispose()

View file

@ -1,10 +1,8 @@
#[cfg(not(feature = "stable"))]
use leptos_reactive::{
create_isomorphic_effect, create_runtime, create_scope, create_signal,
signal_prelude::*, SignalGetUntracked, SignalSetUntracked,
};
#[cfg(not(feature = "stable"))]
#[test]
fn untracked_set_doesnt_trigger_effect() {
use std::{cell::RefCell, rc::Rc};
@ -18,7 +16,7 @@ fn untracked_set_doesnt_trigger_effect() {
create_isomorphic_effect(cx, {
let b = b.clone();
move |_| {
let formatted = format!("Value is {}", a());
let formatted = format!("Value is {}", a.get());
*b.borrow_mut() = formatted;
}
});
@ -36,7 +34,6 @@ fn untracked_set_doesnt_trigger_effect() {
.dispose()
}
#[cfg(not(feature = "stable"))]
#[test]
fn untracked_get_doesnt_trigger_effect() {
use std::{cell::RefCell, rc::Rc};
@ -51,8 +48,11 @@ fn untracked_get_doesnt_trigger_effect() {
create_isomorphic_effect(cx, {
let b = b.clone();
move |_| {
let formatted =
format!("Values are {} and {}", a(), a2.get_untracked());
let formatted = format!(
"Values are {} and {}",
a.get(),
a2.get_untracked()
);
*b.borrow_mut() = formatted;
}
});

View file

@ -10,7 +10,7 @@ readme = "../README.md"
[dependencies]
leptos_reactive = { workspace = true }
server_fn = { workspace = true, default-features = false }
server_fn = { workspace = true}
lazy_static = "1"
serde = { version = "1", features = ["derive"] }
thiserror = "1"
@ -27,7 +27,7 @@ default-tls = ["server_fn/default-tls"]
hydrate = ["leptos_reactive/hydrate"]
rustls = ["server_fn/rustls"]
ssr = ["leptos_reactive/ssr", "server_fn/ssr"]
stable = ["leptos_reactive/stable", "server_fn/stable"]
nightly = ["leptos_reactive/nightly", "server_fn/nightly"]
[package.metadata.cargo-all-features]
denylist = ["stable"]
denylist = ["nightly"]

View file

@ -35,24 +35,24 @@ use std::{cell::Cell, future::Future, pin::Pin, rc::Rc};
/// let version = save_data.version();
///
/// // before we do anything
/// assert_eq!(input(), None); // no argument yet
/// assert_eq!(pending(), false); // isn't pending a response
/// assert_eq!(result_of_call(), None); // there's no "last value"
/// assert_eq!(version(), 0);
/// assert_eq!(input.get(), None); // no argument yet
/// assert_eq!(pending.get(), false); // isn't pending a response
/// assert_eq!(result_of_call.get(), None); // there's no "last value"
/// assert_eq!(version.get(), 0);
/// # if false {
/// // dispatch the action
/// save_data.dispatch("My todo".to_string());
///
/// // when we're making the call
/// // assert_eq!(input(), Some("My todo".to_string()));
/// // assert_eq!(pending(), true); // is pending
/// // assert_eq!(result_of_call(), None); // has not yet gotten a response
/// // assert_eq!(input.get(), Some("My todo".to_string()));
/// // assert_eq!(pending.get(), true); // is pending
/// // assert_eq!(result_of_call.get(), None); // has not yet gotten a response
///
/// // after call has resolved
/// assert_eq!(input(), None); // input clears out after resolved
/// assert_eq!(pending(), false); // no longer pending
/// assert_eq!(result_of_call(), Some(42));
/// assert_eq!(version(), 1);
/// assert_eq!(input.get(), None); // input clears out after resolved
/// assert_eq!(pending.get(), false); // no longer pending
/// assert_eq!(result_of_call.get(), Some(42));
/// assert_eq!(version.get(), 1);
/// # }
/// # });
/// ```
@ -287,24 +287,24 @@ where
/// let version = save_data.version();
///
/// // before we do anything
/// assert_eq!(input(), None); // no argument yet
/// assert_eq!(pending(), false); // isn't pending a response
/// assert_eq!(result_of_call(), None); // there's no "last value"
/// assert_eq!(version(), 0);
/// assert_eq!(input.get(), None); // no argument yet
/// assert_eq!(pending.get(), false); // isn't pending a response
/// assert_eq!(result_of_call.get(), None); // there's no "last value"
/// assert_eq!(version.get(), 0);
/// # if false {
/// // dispatch the action
/// save_data.dispatch("My todo".to_string());
///
/// // when we're making the call
/// // assert_eq!(input(), Some("My todo".to_string()));
/// // assert_eq!(pending(), true); // is pending
/// // assert_eq!(result_of_call(), None); // has not yet gotten a response
/// // assert_eq!(input.get(), Some("My todo".to_string()));
/// // assert_eq!(pending.get(), true); // is pending
/// // assert_eq!(result_of_call.get(), None); // has not yet gotten a response
///
/// // after call has resolved
/// assert_eq!(input(), None); // input clears out after resolved
/// assert_eq!(pending(), false); // no longer pending
/// assert_eq!(result_of_call(), Some(42));
/// assert_eq!(version(), 1);
/// assert_eq!(input.get(), None); // input clears out after resolved
/// assert_eq!(pending.get(), false); // no longer pending
/// assert_eq!(result_of_call.get(), Some(42));
/// assert_eq!(version.get(), 1);
/// # }
/// # });
/// ```

View file

@ -23,8 +23,8 @@ default = []
csr = ["leptos/csr", "leptos/tracing"]
hydrate = ["leptos/hydrate", "leptos/tracing"]
ssr = ["leptos/ssr", "leptos/tracing"]
stable = ["leptos/stable", "leptos/tracing"]
nightly = ["leptos/nightly", "leptos/tracing"]
[package.metadata.cargo-all-features]
denylist = ["stable"]
denylist = ["nightly"]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]

View file

@ -57,7 +57,7 @@ impl std::fmt::Debug for BodyContext {
/// provide_meta_context(cx);
/// let (prefers_dark, set_prefers_dark) = create_signal(cx, false);
/// let body_class = move || {
/// if prefers_dark() {
/// if prefers_dark.get() {
/// "dark".to_string()
/// } else {
/// "light".to_string()

View file

@ -21,14 +21,14 @@
//! view! { cx,
//! <Title
//! // reactively sets document.title when `name` changes
//! text=name
//! text=move || name.get()
//! // applies the `formatter` function to the `text` value
//! formatter=|text| format!("“{text}” is your name")
//! />
//! <main>
//! <input
//! prop:value=name
//! on:input=move |ev| set_name(event_target_value(&ev))
//! prop:value=move || name.get()
//! on:input=move |ev| set_name.set(event_target_value(&ev))
//! />
//! </main>
//! }

View file

@ -60,9 +60,9 @@ default = []
csr = ["leptos/csr"]
hydrate = ["leptos/hydrate"]
ssr = ["leptos/ssr", "dep:cached", "dep:lru", "dep:url", "dep:regex"]
stable = ["leptos/stable"]
nightly = ["leptos/nightly"]
[package.metadata.cargo-all-features]
# No need to test optional dependencies as they are enabled by the ssr feature
denylist = ["url", "regex", "stable"]
denylist = ["url", "regex", "nightly"]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]

View file

@ -140,7 +140,7 @@ where
}
cfg_if::cfg_if! {
if #[cfg(not(feature = "stable"))] {
if #[cfg(feature = "nightly")] {
auto trait NotOption {}
impl<T> !NotOption for Option<T> {}

View file

@ -183,9 +183,9 @@
//! **Important Note:** You must enable one of `csr`, `hydrate`, or `ssr` to tell Leptos
//! which mode your app is operating in.
#![cfg_attr(not(feature = "stable"), feature(auto_traits))]
#![cfg_attr(not(feature = "stable"), feature(negative_impls))]
#![cfg_attr(not(feature = "stable"), feature(type_name_of_val))]
#![cfg_attr(feature = "nightly", feature(auto_traits))]
#![cfg_attr(feature = "nightly", feature(negative_impls))]
#![cfg_attr(feature = "nightly", feature(type_name_of_val))]
mod animation;
mod components;

View file

@ -28,7 +28,7 @@ gloo-net = "0.2"
js-sys = "0.3"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
reqwest = { version = "0.11", default-features = false }
reqwest = { version = "0.11"}
once_cell = "1"
[features]
@ -36,4 +36,4 @@ default = ["default-tls"]
default-tls = ["reqwest/default-tls"]
rustls = ["reqwest/rustls-tls"]
ssr = ["inventory"]
stable = ["server_fn_macro_default/stable"]
nightly = ["server_fn_macro_default/nightly"]

View file

@ -19,4 +19,4 @@ server_fn = { version = "0.2" }
serde = "1"
[features]
stable = ["server_fn_macro/stable"]
nightly = ["server_fn_macro/nightly"]

View file

@ -1,4 +1,4 @@
#![cfg_attr(not(feature = "stable"), feature(proc_macro_span))]
#![cfg_attr(feature = "nightly", feature(proc_macro_span))]
//! This crate contains the default implementation of the #[macro@crate::server] macro without a context from the server. See the [server_fn_macro] crate for more information.
#![forbid(unsafe_code)]

View file

@ -18,4 +18,4 @@ xxhash-rust = { version = "0.8.6", features = ["const_xxh64"] }
const_format = "0.2.30"
[features]
stable = []
nightly = []

View file

@ -1,4 +1,4 @@
#![cfg_attr(not(feature = "stable"), feature(proc_macro_span))]
#![cfg_attr(feature = "nightly", feature(proc_macro_span))]
#![forbid(unsafe_code)]
#![deny(missing_docs)]
//! Implementation of the server_fn macro.