The backend on localhost:3040/todos
accepts GET and POST requests. In the frontend there is a form with an input field and the submit button to send POST. Underneath the form is the list retrieved by GET. A refresh flag flips when a new POST is sent and triggers use_effect_with
with the GET call. The problem is that the GET request is usually faster than POST and I am struggling to find a way to stall the refresh until the POST is processed in the backend.
#[function_component(App)]
fn page_body() -> Html {
let input_value = use_state(|| String::new());
let refresh_flag = use_state(|| false);
let todolist: UseStateHandle<Option<TodoList>> = use_state(|| None);
let form_onsubmit = {
let input_value = input_value.clone();
let refresh_flag = refresh_flag.clone();
Callback::from(move |e: SubmitEvent| {
e.prevent_default();
let new_todo = NewTodo {
title: String::from(input_value.as_str()),
};
wasm_bindgen_futures::spawn_local(async move {
let todos_url: String = format!("http://localhost:3040/todos");
let data_serialized = serde_json::to_string_pretty(&new_todo).unwrap();
let request = Request::post(&todos_url)
.header("Content-Type", "application/json")
.body(wasm_bindgen::JsValue::from(&data_serialized))
.send().await
.unwrap()
.text().await
.unwrap();
});
input_value.set(String::from(""));
refresh_flag.set(!*refresh_flag);
})
};
{ // do this block on page load and when refresh flag is flipped
let todolist = todolist.clone();
use_effect_with(refresh_flag, move |_| {
wasm_bindgen_futures::spawn_local(async move {
let todos_url: String = format!("http://localhost:3040/todos");
let fetched_todos: TodoList = Request::get(&todos_url)
.send().await
.unwrap()
.json().await
.unwrap();
todolist.set(Some(fetched_todos));
});
});
}
html! {
<div>
<div>
<form onsubmit={form_onsubmit}>
<input
type="text"
value={(*input_value).clone()}
oninput={form_oninput}/>
<input type="submit" value="Create TODO" />
</form>
</div>
<div>
<ul>
{
match todolist.as_ref() {
Some(tdl) => tdl
.todos.iter().map(|todo| {
html! {
<li>
<TodoComponent todo={todo.clone()}/>
</li>
}
})
.collect(),
None =>{html! {<>{"No data yet"}</>} },
}
}
</ul>
</div>
</div>
}
}