leptos/docs/COMMON_BUGS.md

2.0 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 />
}