Skip to content

Instantly share code, notes, and snippets.

@echochamber
Last active June 16, 2023 03:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save echochamber/74ddc7511a7e199f11779b6483c84380 to your computer and use it in GitHub Desktop.
Save echochamber/74ddc7511a7e199f11779b6483c84380 to your computer and use it in GitHub Desktop.
// My component which I render.
pub fn Component(cx: Scope) -> Element {
let (form, display) = InitFormAndDisplay(cx);
cx.render(rsx!{
form
div { hr {} }
display
})
}
// Get a handle to both the form and the display elements, which both are using the
// search_result shared state handle to communicate updates.
pub fn InitFormAndDisplay (cx: Scope) -> (Element, Element) {
// Shared state between the form and the display.
let search_result: &UseState<Option<ApiResult>> = use_state(cx, || None);
let search = move |evt: FormEvent| {
// cx.spawn here is only necessary because I want to call an external API with the form content,
// if you just want to do regular form handling stuff, you can do it here without spawning an
// async task using cx.spawn.
cx.spawn({
// Do stuff with the result from the event.
let qString = evt.values["query"].clone();
// Need to do this before enter async block to avoid moved error from borrow checker.
let search_result = search_result.to_owned();
async move {
// Me Calling some external API
let resp = SomeService::new().query(&qString.as_str()).await;
// Handling response from API and Setting relevant data from api in shared state.
match &resp {
Ok(_data) => debug!("Query successful!")
Err(_err) => debug!("Query failed")
}
search_result.set(Some(resp));
}
});
};
(
cx.render(rsx! {
SearchForm {on_submit: move |evt: FormEvent| { search(evt) } }
}),
cx.render(rsx! {
SearchDisplay { search_result: &search_result }
})
)
}
#[inline_props]
pub fn SearchForm<'a> (cx: Scope, on_submit: EventHandler<'a, FormEvent>) -> Element<'a> {
cx.render(rsx! {
form {
prevent_default: "onsubmit",
onsubmit: move |event| on_submit.call(event),
input { id: "query", name: "query", }
button {
value: "Submit",
r#type: "submit",
prevent_default: true,
"Search",
}
}
})
}
#[inline_props]
pub fn SearchDisplay<'a> (cx: Scope<'a>, search_result: &'a UseState<Option<Result>>) -> Element<'a> {
cx.render(match search_result.get() {
// You can just do regular rsx here, I'm matching because I need to handle the result of my API
// call from above
Some(Ok(response)) => {
// API call is done, render results
e @ Some(Err(_)) => {
// API Call is done and errored. Render error
}
_ => rsx! {
// Waiting for API call to finish, show loading indicator.
},
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment