mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
change: migrate to nightly
and csr
features rather than stable
and default-features = false
(#1227)
This commit is contained in:
parent
f5cfe4e8a2
commit
ee7dbafc85
78 changed files with 430 additions and 483 deletions
6
.github/ISSUE_TEMPLATE/bug_report.md
vendored
6
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -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**
|
||||
|
|
20
Cargo.toml
20
Cargo.toml
|
@ -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]
|
||||
|
|
10
README.md
10
README.md
|
@ -68,7 +68,7 @@ Here are some resources for learning more about Leptos:
|
|||
|
||||
## `nightly` Note
|
||||
|
||||
Most of the examples assume you’re using `nightly` version of Rust. For this, you can either set your toolchain globally or on per-project basis.
|
||||
Most of the examples assume you’re 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 haven’t already):
|
||||
|
||||
|
@ -86,13 +86,7 @@ channel = "nightly"
|
|||
targets = ["wasm32-unknown-unknown"]
|
||||
```
|
||||
|
||||
If you’re 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 you’re using `stable`,
|
||||
you’ll 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`
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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" }
|
|
@ -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"] }
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"] }
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 = [
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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>
|
||||
/// }
|
||||
/// # });
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 you’re using `nightly` Rust. If you’re 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 you’re using `stable`,
|
||||
//! you’ll 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>
|
||||
//! }
|
||||
|
|
|
@ -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!"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"]]
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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>>;
|
||||
|
||||
|
|
|
@ -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"]]
|
||||
|
|
|
@ -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 didn’t 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 didn’t 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 don’t."</div> }
|
||||
/// view! { cx, <div class:hidden-div={move || count.get() < 3}>"Now you see me, now you don’t."</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 don’t."</div> }
|
||||
/// view! { cx, <div class:hidden-div-25={move || count.get() < 3}>"Now you see me, now you don’t."</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 don’t."
|
||||
/// </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>
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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());
|
||||
//! });
|
||||
//! });
|
||||
//! ```
|
||||
|
|
|
@ -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();
|
||||
/// #
|
||||
/// ```
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
///
|
||||
/// # });
|
||||
/// ```
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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);
|
||||
/// # }
|
||||
/// # });
|
||||
/// ```
|
||||
|
|
|
@ -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"]]
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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>
|
||||
//! }
|
||||
|
|
|
@ -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"]]
|
||||
|
|
|
@ -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> {}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -19,4 +19,4 @@ server_fn = { version = "0.2" }
|
|||
serde = "1"
|
||||
|
||||
[features]
|
||||
stable = ["server_fn_macro/stable"]
|
||||
nightly = ["server_fn_macro/nightly"]
|
||||
|
|
|
@ -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)]
|
||||
|
||||
|
|
|
@ -18,4 +18,4 @@ xxhash-rust = { version = "0.8.6", features = ["const_xxh64"] }
|
|||
const_format = "0.2.30"
|
||||
|
||||
[features]
|
||||
stable = []
|
||||
nightly = []
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue