yew/functional/hooks/
use_state.rs1use std::fmt;
2use std::mem::transmute;
3use std::ops::Deref;
4use std::rc::Rc;
5
6use implicit_clone::ImplicitClone;
7
8use super::{use_reducer, use_reducer_eq, Reducible, UseReducerDispatcher, UseReducerHandle};
9use crate::functional::hook;
10use crate::html::IntoPropValue;
11use crate::Callback;
12
13#[repr(transparent)]
14struct UseStateReducer<T> {
15 value: T,
16}
17
18impl<T> Reducible for UseStateReducer<T> {
19 type Action = T;
20
21 fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
22 Rc::new(Self { value: action })
23 }
24}
25
26impl<T> PartialEq for UseStateReducer<T>
27where
28 T: PartialEq,
29{
30 fn eq(&self, rhs: &Self) -> bool {
31 self.value == rhs.value
32 }
33}
34
35#[hook]
82pub fn use_state<T, F>(init_fn: F) -> UseStateHandle<T>
83where
84 T: 'static,
85 F: FnOnce() -> T,
86{
87 let handle = use_reducer(move || UseStateReducer { value: init_fn() });
88
89 UseStateHandle { inner: handle }
90}
91
92#[hook]
96pub fn use_state_eq<T, F>(init_fn: F) -> UseStateHandle<T>
97where
98 T: PartialEq + 'static,
99 F: FnOnce() -> T,
100{
101 let handle = use_reducer_eq(move || UseStateReducer { value: init_fn() });
102
103 UseStateHandle { inner: handle }
104}
105
106pub struct UseStateHandle<T> {
108 inner: UseReducerHandle<UseStateReducer<T>>,
109}
110
111impl<T: fmt::Debug> fmt::Debug for UseStateHandle<T> {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 f.debug_struct("UseStateHandle")
114 .field("value", &format!("{:?}", **self))
115 .finish_non_exhaustive()
116 }
117}
118
119impl<T> UseStateHandle<T> {
120 pub fn value_rc(&self) -> Rc<T> {
125 unsafe { transmute::<Rc<UseStateReducer<T>>, Rc<T>>(self.inner.value_rc()) }
128 }
129
130 pub fn set(&self, value: T) {
132 self.inner.dispatch(value)
133 }
134
135 pub fn setter(&self) -> UseStateSetter<T> {
137 UseStateSetter {
138 inner: self.inner.dispatcher(),
139 }
140 }
141
142 pub fn into_inner(self) -> (Rc<T>, UseStateSetter<T>) {
145 let (data, inner) = self.inner.into_inner();
146 (
148 unsafe { transmute::<Rc<UseStateReducer<T>>, Rc<T>>(data) },
149 UseStateSetter { inner },
150 )
151 }
152}
153
154impl<T> Deref for UseStateHandle<T> {
155 type Target = T;
156
157 fn deref(&self) -> &Self::Target {
158 &self.inner.value
159 }
160}
161
162impl<T> Clone for UseStateHandle<T> {
163 fn clone(&self) -> Self {
164 Self {
165 inner: self.inner.clone(),
166 }
167 }
168}
169
170impl<T> PartialEq for UseStateHandle<T>
171where
172 T: PartialEq,
173{
174 fn eq(&self, rhs: &Self) -> bool {
175 self.inner == rhs.inner
176 }
177}
178
179impl<T> ImplicitClone for UseStateHandle<T> {}
180
181pub struct UseStateSetter<T> {
183 inner: UseReducerDispatcher<UseStateReducer<T>>,
184}
185
186impl<T> Clone for UseStateSetter<T> {
187 fn clone(&self) -> Self {
188 Self {
189 inner: self.inner.clone(),
190 }
191 }
192}
193
194impl<T> fmt::Debug for UseStateSetter<T>
195where
196 T: fmt::Debug,
197{
198 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199 f.debug_struct("UseStateSetter").finish_non_exhaustive()
200 }
201}
202
203impl<T> From<UseStateSetter<T>> for Callback<T> {
204 fn from(value: UseStateSetter<T>) -> Self {
205 Self::from(value.inner)
206 }
207}
208
209impl<T> IntoPropValue<Callback<T>> for UseStateSetter<T> {
210 fn into_prop_value(self) -> Callback<T> {
211 self.inner.into_prop_value()
212 }
213}
214
215impl<T> PartialEq for UseStateSetter<T> {
216 fn eq(&self, rhs: &Self) -> bool {
217 self.inner == rhs.inner
218 }
219}
220
221impl<T> ImplicitClone for UseStateSetter<T> {}
222
223impl<T> UseStateSetter<T> {
224 pub fn set(&self, value: T) {
226 self.inner.dispatch(value)
227 }
228
229 pub fn to_callback(&self) -> Callback<T> {
232 self.inner.to_callback()
233 }
234}