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 127 128
use std::convert::TryInto; use js_sys::Function; use serde::{de::DeserializeOwned, Serialize}; use wasm_bindgen::prelude::*; use crate::ReactObservable; #[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) // }