1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
use std::convert::TryInto;
use js_sys::Function;
use serde::{de::DeserializeOwned, Serialize};
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "react")]
extern "C" {
/// Binding to React.useState
#[wasm_bindgen(js_name = useState)]
fn js_use_state(initial_value: JsValue) -> js_sys::Array;
/// Binding to React.useEffect
#[wasm_bindgen(js_name = useEffect)]
fn js_use_effect(effect: &Closure<dyn FnMut()>, bindings: js_sys::Array) -> js_sys::Array;
/// Binding to React.useReducer
#[wasm_bindgen(js_name = useReducer)]
fn js_use_reducer(reducer: &Closure<dyn FnMut()>, initial_value: JsValue) -> js_sys::Array;
}
// Duck type for React components
#[wasm_bindgen]
extern "C" {
pub type ReactComponent;
#[wasm_bindgen(structural, method)]
pub fn forceUpdate(this: &ReactComponent);
}
/// Oxidized interface to React.useState
pub fn use_state<T>(initial_value: T) -> (T, impl Fn(T))
where
T: Serialize + DeserializeOwned,
{
#[allow(unused_unsafe)]
let jsa = unsafe { js_use_state(JsValue::from_serde(&initial_value).unwrap()) };
let current = jsa.get(0).into_serde().unwrap();
let update: Function = jsa.get(1).try_into().unwrap();
let cb = move |value: T| {
// unimplemented!()
update
.call1(&JsValue::UNDEFINED, &JsValue::from_serde(&value).unwrap())
.unwrap();
};
(current, cb)
}
// /// Oxidized interface to React.useEffect
// pub fn use_effect<T, E>(effect: E, props: Vec<T>)
// where
// T: Serialize + DeserializeOwned,
// E: Fn(T) -> fn(),
// {
// // #[allow(unused_unsafe)]
// // let jsa = unsafe { js_use_state(JsValue::from_serde(&initial_value).unwrap()) };
// // let current = jsa.get(0).into_serde().unwrap();
// // let update: Function = jsa.get(1).try_into().unwrap();
// // let cb = move |value: T| {
// // // unimplemented!()
// // update
// // .call1(&JsValue::UNDEFINED, &JsValue::from_serde(&value).unwrap())
// // .unwrap();
// // };
// // (current, cb)
// unimplemented!()
// }
// /// Oxidized interface to React.useReducer
// pub fn use_reducer<T, R>(reducer: R, initial_value: T) -> (T, fn())
// where
// T: Serialize + DeserializeOwned,
// R: Into<Closure<dyn Fn(T) -> T>>,
// {
// #[allow(unused_unsafe)]
// let jsa =
// unsafe { js_use_reducer(reducer.into(), JsValue::from_serde(&initial_value).unwrap()) };
// let current = jsa.get(0).into_serde().unwrap();
// let update: Function = jsa.get(1).try_into().unwrap();
// let cb = move |value: T| {
// // // unimplemented!()
// update
// .call1(&JsValue::UNDEFINED, &JsValue::from_serde(&value).unwrap())
// .unwrap();
// };
// // (current, cb)
// unimplemented!()
// }
// fn forceupdate_reducer(x: usize) -> usize {
// x + 1
// }
// pub fn use_force_update() {
// let closure = Closure::wrap(Box::new(|| {}));
// // let jsa = unsafe {
// // js_use_reducer(
// // Closure::wrap(Box::new(|x: JsValue| {}))
// // .as_ref()
// // .unchecked_ref(),
// // 0.into(),
// // )
// // };
// let current = jsa.get(0).into_serde().unwrap();
// let update: Function = jsa.get(1).try_into().unwrap();
// let cb = move |value: T| {
// // // unimplemented!()
// update
// .call1(&JsValue::UNDEFINED, &JsValue::from_serde(&value).unwrap())
// .unwrap();
// };
// // (current, cb)
// }