|
| 1 | +#[cfg(feature = "import-react")] |
| 2 | +macro_rules! wasm_bindgen_react_state_helpers { |
| 3 | + ($($b:item)+) => { |
| 4 | + #[wasm_bindgen(inline_js = r#" |
| 5 | + import * as React from "react"; |
| 6 | + export { React }; |
| 7 | + export function use_state_object(initial_value) { |
| 8 | + const [state, set_state] = React.useState(initial_value); |
| 9 | + return { value: state, setter: { set_state } }; |
| 10 | + } |
| 11 | + export function use_state_auto_clean(initial_value, clean) { |
| 12 | + const obj = use_state_object(initial_value); |
| 13 | + const state = obj.value; |
| 14 | + React.useEffect(() => { clean(state) }, [state]); |
| 15 | + } |
| 16 | + "#)] |
| 17 | + extern "C" { |
| 18 | + $($b)+ |
| 19 | + } |
| 20 | + }; |
| 21 | +} |
| 22 | + |
| 23 | +#[cfg(not(feature = "import-react"))] |
| 24 | +macro_rules! wasm_bindgen_react_state_helpers { |
| 25 | + ($($b:item)+) => { |
| 26 | + #[wasm_bindgen(inline_js = r#" |
| 27 | + export function use_state_object(initial_value) { |
| 28 | + const [state, set_state] = React.useState(initial_value); |
| 29 | + return { value: state, setter: { set_state } }; |
| 30 | + } |
| 31 | + export function use_state_auto_clean(initial_value, clean) { |
| 32 | + const obj = use_state_object(initial_value); |
| 33 | + const state = obj.value; |
| 34 | + React.useEffect(() => { clean(state) }, [state]); |
| 35 | + } |
| 36 | + "#)] |
| 37 | + extern "C" { |
| 38 | + $($b)+ |
| 39 | + } |
| 40 | + }; |
| 41 | +} |
| 42 | + |
| 43 | +macro_rules! define_react_use_state_for_type { |
| 44 | + ( { value: $type_value:ty, $($t:tt)+ } ) => { |
| 45 | + define_react_use_state_for_type! {{ |
| 46 | + input: $type_value, |
| 47 | + output: $type_value, |
| 48 | + $($t)+ |
| 49 | + }} |
| 50 | + }; |
| 51 | + ({ |
| 52 | + input: $type_input:ty, |
| 53 | + output: $type_output:ty, |
| 54 | + object: $name_object:ident, |
| 55 | + setter: $name_setter:ident, |
| 56 | + use_state: $name_use:ident, |
| 57 | + use_state_with: $name_use_with:ident, |
| 58 | + auto_clean: $name_clean:ident, |
| 59 | + auto_clean_with: $name_clean_with:ident |
| 60 | + $(,)? |
| 61 | + }) => { |
| 62 | + wasm_bindgen_react_state_helpers! { |
| 63 | + #[derive(Debug, Clone)] |
| 64 | + pub type $name_object; |
| 65 | + #[wasm_bindgen(structural, method, getter)] |
| 66 | + fn value(this: &$name_object) -> $type_output; |
| 67 | + #[wasm_bindgen(structural, method, getter)] |
| 68 | + fn setter(this: &$name_object) -> $name_setter; |
| 69 | + |
| 70 | + #[derive(Debug, Clone)] |
| 71 | + pub type $name_setter; |
| 72 | + #[wasm_bindgen(structural, method)] |
| 73 | + fn set_state(this: &$name_setter, value: $type_input); |
| 74 | + /// Closure `get_value_from_old` will be called immediately, |
| 75 | + /// thus it is safe to use reference here |
| 76 | + /// |
| 77 | + /// Closure get_value_from_old will be called only once |
| 78 | + #[wasm_bindgen(structural, method, js_name = "set_state")] |
| 79 | + fn set_state_with( |
| 80 | + this: &$name_setter, |
| 81 | + get_value_from_old: &mut dyn FnMut($type_output) -> $type_input, |
| 82 | + ); |
| 83 | + |
| 84 | + /// `React.useState<T>(initial_value)` |
| 85 | + #[wasm_bindgen(js_name = "use_state_object")] |
| 86 | + fn $name_use(initial_value: $type_input) -> $name_object; |
| 87 | + |
| 88 | + /// `React.useState<T>(get_initial_value)` |
| 89 | + #[wasm_bindgen(js_name = "use_state_object")] |
| 90 | + #[doc = concat!("React.useState<`", stringify!($type_input), "`>(initial_value)")] |
| 91 | + fn $name_use_with( |
| 92 | + initial_value: &mut dyn FnMut() -> $type_input, |
| 93 | + ) -> $name_object; |
| 94 | + |
| 95 | + #[wasm_bindgen(js_name = "use_state_auto_clean")] |
| 96 | + fn $name_clean( |
| 97 | + initial_value: $type_input, |
| 98 | + free: &Closure<dyn FnMut($type_output)>, |
| 99 | + ) -> $name_object; |
| 100 | + |
| 101 | + #[wasm_bindgen(js_name = "use_state_auto_clean")] |
| 102 | + fn $name_clean_with( |
| 103 | + get_initial_value: &mut dyn FnMut() -> $type_input, |
| 104 | + free: &Closure<dyn FnMut($type_output)>, |
| 105 | + ) -> $name_object; |
| 106 | + } |
| 107 | + }; |
| 108 | +} |
| 109 | + |
| 110 | +macro_rules! define_react_use_state_helpers { |
| 111 | + ($($t:tt),+ $(,)?) => { |
| 112 | + $( define_react_use_state_for_type!{ $t } )+ |
| 113 | + }; |
| 114 | +} |
| 115 | + |
| 116 | +pub(super) use define_react_use_state_for_type; |
| 117 | +pub(super) use define_react_use_state_helpers; |
| 118 | +pub(super) use wasm_bindgen_react_state_helpers; |
0 commit comments