Client-side global asyncronous state #3996
-
Hey Dioxus community! I'm wanting to load data from a client-side database connection. enum Creds {
Guest,
User { email: EmailAddress, password: String }
}
async fn connect_to_db(creds: Creds) -> Result<Conn, MyError> { ... } I want this state to be rendered (reactively) in the UI (a small indicator that flashes red when failing/failed to connect). Also, I want to be able to mutate this global state when the user logs in, i.e. presses the login button or sign-up button, which requires calling pub enum DbState {
StillLoading,
Connected(Conn),
Errored(MyError),
}
impl DbState {
pub fn from_context() -> RwSignal<DbState> {
leptos::prelude::expect_context()
}
pub fn provide_context() {
leptos::prelude::provide_context(RwSignal::new(DbState::StillLoading));
}
}
pub fn LoadDb() -> impl IntoView {
let resource = LocalResource::new(move || {
// logic
let new_db_conn = connect_to_db(/* logic /*).await;
DbState::from_context().set(new_db_conn);
});
// stuff to render based on resource.value()
} But, just based on these primitives I found on the dioxus docs, I'm not even sure this is possible without storing some sort of non-reactive
So how can I get my UI components to use this global state while reactively re-rendering upon db connection changes? Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
You can put signals inside of context which can be modified and react to changes. Just make sure that the signals have the same scope as the context. (e.g. e.g. fn main() {
dioxus::launch(App);
}
#[derive(Clone, Copy)]
struct ToggleCtx {
toggled: Signal<bool>,
}
#[component]
fn App() -> Element {
let toggle_ctx = use_context_provider(|| ToggleCtx { toggled: Signal::new(false) });
let value = (toggle_ctx.toggled)();
rsx! {
"Is toggled: {value}",
ToggleButton {}
}
}
#[component]
fn ToggleButton() -> Element {
let ctx: ToggleCtx = use_context();
rsx! {
button {
onclick: move |_| ctx.toggled.toggle(),
"Toggle!"
}
}
} You can also pass resources and memos through context just fine - the same scope stuff I mentioned above also applies to these. |
Beta Was this translation helpful? Give feedback.
You can put signals inside of context which can be modified and react to changes.
Just make sure that the signals have the same scope as the context. (e.g.
use_root_context
will needSignal::new_in_scope(ScopeId::ROOT))
- I would instead suggest creating the context and signals in the same scope, such as the top-levelApp
component, to avoid that issue.e.g.