structs containing Vec<T>, HashSet<T> and HashMap<T, T> are not working with Signal/ServerFn
Problem
Steps To Reproduce Reproducile repo
#[component]
fn Home() -> Element {
let global_filter: Signal<GlobalFilter> = use_signal(|| GlobalFilter::default());
rsx! {
button {
onclick: move |_| {
let filter: GlobalFilter = global_filter.read_unchecked().to_owned();
async move {
get_server_data(filter).await;
}
},
"Button"
}
}
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct GlobalFilter {
pub test_string: String,
pub test_vec: Vec<String>,
pub test_hashset: HashSet<String>,
pub test_hashmap: HashMap<String, String>,
// wrap them in Option to bypass the bug
// pub test_vec: Option<Vec<String>>,
// pub test_hashset: Option<HashSet<String>>,
// pub test_hashmap: Option<HashMap<String, String>>,
}
#[server]
async fn get_server_data(global_filter: GlobalFilter) -> Result<(), ServerFnError> {
Ok(())
}
After clicking the button, an error( can be observed in browser's dev tool)
Args|missing field `test_vec`
happened. This error happened both on 0.5 and the main branch.
After digging on discord, the tmp solution is to wrap those fields in an Option. Evan mentioned it should be fixed in https://github.com/DioxusLabs/dioxus/pull/2288 but looks like the above case is not covered.
Expected behavior Those fields in the struct should work without the extra Option
Environment:
- Dioxus version: 0.5 and main
- Rust version: 1.79
- OS info: Debian 12
- App platform: Fullstack
The default server function encoding is post url which doesn't support nested types. You can set the input and output encoding manually with this syntax:
#[server(input = Json, output = Json)]
async fn get_server_data(global_filter: GlobalFilter) -> Result<(), ServerFnError> {
Ok(())
}
Dioxus should probably choose a more capable default encoding for server functions to make this work by default