Replies: 1 comment 5 replies
-
Currently, cloning is the best way to do this. If you want to make the value copy inside of the child component you can make it accept I've been experimenting with better apis for mapping readable values in #4413 which could make this nicer. One version of this we could support in the future is making Resource act more like a store which wouldn't require cloning the value (although it does currently require some ugly wrapper types): use dioxus::prelude::{
dioxus_stores::{use_store, Store},
*,
};
use std::num::ParseIntError;
fn main() {
dioxus::launch(app);
}
fn app() -> Element {
let result = use_store(|| {
"0".parse::<u32>()
.map(|data| TodoState { data })
.map_err(|error| ParseError { error })
});
match result.as_result() {
Ok(data) => {
rsx! {
HandleOk { data }
}
}
Err(error) => {
rsx! {
HandleError { error }
}
}
}
}
#[component]
fn HandleError(error: Store<ParseError>) -> Element {
rsx! {
h1 { "Error parsing number" }
p { "An error occurred while parsing the number: {error.error()}" }
}
}
#[component]
fn HandleOk(data: Store<TodoState>) -> Element {
rsx! {
h1 { "Parsed number successfully" }
p { "The parsed number is: {data.data()}" }
}
}
#[derive(Store)]
struct TodoState {
#[store(foreign)]
data: u32,
}
#[derive(Store)]
struct ParseError {
#[store(foreign)]
error: ParseIntError,
} |
Beta Was this translation helpful? Give feedback.
5 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Is there any recommended and easy way to pass values returned from
use_resource
to child components?The main way of accessing values from
use_resource
is&*resource.read_unchecked()
, which returns a reference. However, components cannot accept references, so that value needs to be converted to owned before it can be passed to them.For simple types, such as
&String
, it seems that Dioxus already does some implicit conversion (or cloning?), as can be seen on the docs page example foruse_resource
. In this example, theweather
variable that is passed to theWeatherElement
component inside thematch
case is actually&String
, but it's still accepted by theWeatherElement
which only accepts the ownedString
.However, this doesn't work for more complex types, such as
Vec
. In that example, functions and components can be slightly modified to use the weather asVec<String>
:However, this now fails, as
WeatherElement
expectsVec<String>
, butweather
inside the match case is&Vec<String>
:I found three ways to fix this problem, but none of them seem to be efficient and ergonomic:
The first one is to just convert the value to the owned type, for example with
.to_vec()
or.clone()
when passing it to the component. However, this doesn't seem to be so ergonomic, as it makes passing arguments longer to type. Also, it doesn't seem to be efficient to clone the value for every component if there are more of them, especially if the value has to be passed to additional components inside child components and cloned there again.The second one is to apply
use_signal
inside the match case, before calling thersx!
macro, and modify the child component to instead acceptSignal
s:The advantage of this option is that you can still pass parameters to components in the short form, and that you don't have to clone the value each time, even in child components. However, Adding an additional block inside the match case before the
rsx!
macro doesn't seem so nice, and adds an additional level of indentation. Also, I'm not sure if it follows the rules of hooks, so if the order of hooks is always the same. I'm currently using this in my project and it seems to work, but hooks aren't very complex.The third option is to create signals directly inside
use_resource
:This option looks quite nice to use, apart from having to dereference the parameter before passing it to the component, which makes component calls longer. However, it probably violates the rules of hooks, as
use_signal
is created inside the initialization closure ofuse_resource
. But in this simple example, it works fine.Are there any better options for passing values to child components? If not, I have some ideas how maybe this could be implemented.
The most intuitive way would be to just use references to these values in child components. However, Dioxus components can't accept references, and I don't known if this can be easily supported without drastically changing how Dioxus works.
Another idea could be to have a
use_resource
-like hook (or an option to the existinguse_resource
that wraps the response inSignal
, like in the third option, but ensuring the order of hooks is always correct. Since changing the value doesn't really make sense, as it's dynamically obtained inuse_resource
, it should probably be some kind of read-onlySignal
-like structure, which just ensures the internal reference lives long enough and handles resctivity whenuse_resource
changes.A related idea is to change the
rsx!
parser to allow (de)referencing component parameters in the short form, so things like this would be possible:Or, maybe this could even be implicit, like it already seems to be the case with
&String
.Beta Was this translation helpful? Give feedback.
All reactions