dioxus
dioxus copied to clipboard
Checkbox inputs sometimes ignore value of `checked` attribute
Problem
I'm trying to make a controlled checkbox, and I can't always seem to control the value of the input element with the checked attribute.
Steps To Reproduce
Here's an extremely contrived but fairly minimum reproducer:
#![allow(non_snake_case)]
use dioxus::prelude::*;
use log::LevelFilter;
fn main() {
dioxus_web::launch(App);
dioxus_logger::init(LevelFilter::Info).expect("failed to init logger");
}
fn App(cx: Scope) -> Element {
let is_checked = use_state(cx, || false);
log::info!("{}", is_checked.get());
cx.render(rsx! {
input {
r#type: "checkbox",
checked: *is_checked.get(),
onclick: |_| is_checked.set(true),
}
button {
onclick: move |_| is_checked.set(!is_checked),
"toggle checked",
}
})
}
run this with dx serve.
Expected behavior
You should see a checkbox and a button. Clicking the checkbox should always make the checkbox checked, clicking the button should toggle the state of the checkbox. In practice, the checkbox state is initialized to the value of is_checked on it's initial mount, but is then toggled on click regardless of the value of is_checked. However, the button will correctly update the checkbox to the value of is_checked.
Adding the prevent_default: "onclick" attribute to the input element will prevent any visual changes from happening to the checkbox when clicked...clicking a checked checkbox remains checked, clicking an unchecked checkbox remains unchecked. The button still correctly resets the state correctly.
Environment:
- Dioxus version: 0.4.3
- Rust version: 1.75.0
- OS info: Linux
- App platform: web
Questionnaire
- [ ] I'm interested in fixing this myself but don't know where to start
- [ ] I would like to fix and I have a solution
- [x] I don't have time to fix this right now, but maybe later
While the input type is radio instead of a checkbox, the following code meets your expectations:
fn App(cx: Scope) -> Element {
let is_checked = use_state(cx, || false);
render! {
input {
r#type: "radio",
checked: *is_checked.get(),
onclick: move |_| {
is_checked.set(true);
}
}
button {
onclick: move |_| is_checked.set(!is_checked),
"toggle checked",
}
}
}
SolidJS has a similar behavior - attempting to control a checkbox like this does not fit with the one-way dataflow paradigm we encourage. In Dioxus we force a re-render since we don't compare values with set, but the bugged behavior remains.
I don't think we can fix this without special casing "checked" checks.
https://playground.solidjs.com/anonymous/2dec7f19-bae4-4d02-ab3c-6f606a577622