How to update state after a JavaScript Promise resolves in use_effect?
#11
-
|
This is my code so far: use js_sys::{Object, Reflect};
use wasm_bindgen::closure::Closure;
use wasm_bindgen_futures::{self, JsFuture};
use wasm_react::{
h,
hooks::{use_effect, use_state, Deps},
Component, VNode,
};
use web_sys::{console::log_1, window, MediaStreamConstraints};
pub struct CanCamera;
impl Component for CanCamera {
fn render(&self) -> VNode {
let resolved = use_state(|| false);
use_effect(
{
let video_object = Object::new();
Reflect::set(&video_object, &"facingMode".into(), &"user".into()).unwrap();
let js_promise = window()
.unwrap()
.navigator()
.media_devices()
.unwrap()
.get_user_media_with_constraints(
&MediaStreamConstraints::new().video(&video_object),
)
.unwrap();
move || || ()
},
Deps::none(),
);
h!(h1).build("can camera")
}
}How to change the state after |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 3 replies
-
|
I figured out how to run resolve / reject callbacks, but they cannot change the state in the way I did it here: use js_sys::{Object, Reflect};
use std::{future::Future, thread};
use wasm_bindgen::{closure::Closure, convert::IntoWasmAbi, JsValue};
use wasm_bindgen_futures::{self, JsFuture};
use wasm_react::{
h,
hooks::{use_effect, use_state, Deps},
Component, VNode,
};
use web_sys::{console::log_1, window, MediaStreamConstraints};
pub struct CanCamera {
closure_resolved: Closure<dyn FnMut(JsValue)>,
closure_rejected: Closure<dyn FnMut(JsValue)>,
}
impl CanCamera {
pub fn new() -> CanCamera {
CanCamera {
closure_resolved: Closure::new(|v| {
log_1(&"resolved".into());
}),
closure_rejected: Closure::new(|v| {
log_1(&"rejected".into());
}),
}
}
}
impl Component for CanCamera {
fn render(&self) -> VNode {
let resolved = use_state(|| false);
use_effect(
{
let video_object = Object::new();
Reflect::set(&video_object, &"facingMode".into(), &"user".into()).unwrap();
let js_promise = window()
.unwrap()
.navigator()
.media_devices()
.unwrap()
.get_user_media_with_constraints(
&MediaStreamConstraints::new().video(&video_object),
)
.unwrap();
drop(js_promise.then2(&self.closure_resolved, &self.closure_rejected));
move || || ()
},
Deps::none(),
);
h!(h1).build("can camera")
}
} |
Beta Was this translation helpful? Give feedback.
-
|
I figured out how to do it: use js_sys::{Object, Reflect};
use wasm_bindgen::{closure::Closure, JsValue};
use wasm_react::{
h,
hooks::{use_effect, use_ref, use_state, Deps},
Component, VNode,
};
use web_sys::{console::log_1, window, MediaStreamConstraints};
pub struct CanCamera {}
impl CanCamera {
pub fn new() -> CanCamera {
CanCamera {}
}
}
struct Magic {
closure_resolved: Closure<dyn FnMut(JsValue)>,
closure_rejected: Closure<dyn FnMut(JsValue)>,
}
impl Component for CanCamera {
fn render(&self) -> VNode {
let resolved = use_state(|| false);
let magic_ref = use_ref({
let mut resolved_0 = resolved.clone();
let mut resolved_1 = resolved.clone();
Magic {
closure_resolved: Closure::new(move |v| {
resolved_0.set(|mut _resolved| true);
log_1(&"resolved".into());
log_1(&v);
}),
closure_rejected: Closure::new(move |v| {
resolved_1.set(|mut _resolved| true);
log_1(&"rejected".into());
}),
}
});
use_effect(
{
log_1(&"effect".into());
let video_object = Object::new();
Reflect::set(&video_object, &"facingMode".into(), &"user".into()).unwrap();
let js_promise = window()
.unwrap()
.navigator()
.media_devices()
.unwrap()
.get_user_media_with_constraints(
&MediaStreamConstraints::new().video(&video_object),
)
.unwrap();
drop(js_promise.then2(
&magic_ref.current().closure_resolved,
&magic_ref.current().closure_rejected,
));
move || || ()
},
Deps::none(),
);
let resolved = resolved.value().to_owned();
if resolved {
log_1(&"rendering after promise resolved".into());
}
h!(h1).build(match resolved {
true => "Got",
false => "Getting camera",
})
}
} |
Beta Was this translation helpful? Give feedback.
-
|
For Promise-handling, you can consider using a crate such as wasm-bindgen-futures to transform promises into futures. |
Beta Was this translation helpful? Give feedback.
@yishn I tried using
JsFuture::from(js_promise)but I didn't have a way of running the future. After looking at the link you sent I found a useful functionspawn_localwhich I used in a way that works: