2.8 KiB
Leptos Gotchas: Common Bugs
This document is intended as a running list of common issues, with example code and solutions.
Reactivity
Avoid writing to a signal from an effect
Issue: Sometimes you want to update a reactive signal in a way that depends on another signal.
let (a, set_a) = create_signal(cx, 0);
let (b, set_b) = create_signal(cx, false);
create_effect(cx, move |_| {
if a() > 5 {
set_b(true);
}
});
This creates an inefficient chain of updates, and can easily lead to infinite loops in more complex applications.
Solution: Follow the rule, What can be derived, should be derived. In this case, this has the benefit of massively reducing the code size, too!
let (a, set_a) = create_signal(cx, 0);
let b = move || a () > 5;
Templates and the DOM
<input value=...>
doesn't update or stops updating
Many DOM attributes can be updated either by setting an attribute on the DOM node, or by setting an object property directly on it. In general, setAttribute()
stops working once the property has been set.
This means that in practice, attributes like value
or checked
on an <input/>
element only update the default value for the <input/>
. If you want to reactively update the value, you should use prop:value
instead to set the value
property.
let (a, set_a) = create_signal(cx, "Starting value".to_string());
let on_input = move |ev| set_a(event_target_value(&ev));
view! {
cx,
// ❌ reactivity doesn't work as expected: typing only updates the default
// of each input, so if you start typing in the second input, it won't
// update the first one
<input value=a on:input=on_input />
<input value=a on:input=on_input />
}
let (a, set_a) = create_signal(cx, "Starting value".to_string());
let on_input = move |ev| set_a(event_target_value(&ev));
view! {
cx,
// ✅ works as intended by setting the value *property*
<input prop:value=a on:input=on_input />
<input prop:value=a on:input=on_input />
}
Build configuration
Cargo feature resolution in workspaces
A new version of Cargo's feature resolver was introduced for the 2021 edition of Rust.
For single crate projects it will select a resolver version based on the Rust edition in Cargo.toml
. As there is no Rust edition present for Cargo.toml
in a workspace, Cargo will default to the pre 2021 edition resolver.
This can cause issues resulting in non WASM compatible code being built for a WASM target. Seeing mio
failing to build is often a sign that none WASM compatible code is being included in the build.
The resolver version can be set in the workspace Cargo.toml
to remedy this issue.
[workspace]
members = ["member1", "member2"]
resolver = "2"