@@ -62,20 +62,24 @@ where
6262
6363impl < T , E , K : Eq + Hash > Drop for UseQueryCleaner < T , E , K > {
6464 fn drop ( & mut self ) {
65- let was_last_listener = {
66- let mut queries_registry = self . client . queries_registry . write_unchecked ( ) ;
67- let query_listeners = queries_registry. get_mut ( & self . registry_entry ) . unwrap ( ) ;
68- // Remove this listener
69- query_listeners. listeners . remove ( & self . scope_id ) ;
70- query_listeners. listeners . is_empty ( )
65+ let mut queries_registry = match self . client . queries_registry . try_write_unchecked ( ) {
66+ Err ( dioxus_lib:: prelude:: BorrowMutError :: Dropped ( _) ) => {
67+ // It's safe to skip this error as the RadioStation's signals could have been dropped before the caller of this function.
68+ // For instance: If you closed the app, the RadioStation would be dropped along all it's signals, causing the inner components
69+ // to still have dropped signals and thus causing this error if they were to call the signals on a custom destructor.
70+ return ;
71+ }
72+ Err ( e) => panic ! ( "Unexpected error: {e}" ) ,
73+ Ok ( v) => v,
7174 } ;
7275
76+ let query_listeners = queries_registry. get_mut ( & self . registry_entry ) . unwrap ( ) ;
77+ // Remove this listener
78+ query_listeners. listeners . remove ( & self . scope_id ) ;
79+
7380 // Clear the queries registry of this listener if it was the last one
74- if was_last_listener {
75- self . client
76- . queries_registry
77- . write_unchecked ( )
78- . remove ( & self . registry_entry ) ;
81+ if query_listeners. listeners . is_empty ( ) {
82+ queries_registry. remove ( & self . registry_entry ) ;
7983 }
8084 }
8185}
@@ -126,73 +130,61 @@ where
126130 K : ' static + Eq + Hash + Clone ,
127131{
128132 let client = use_query_client ( ) ;
129- use_memo_with_old_value (
130- query_keys. clone ( ) ,
131- |prev_query : Option < UseQuery < T , E , K > > | {
132- // If there is an previous query it means they query keys have changed.
133- if let Some ( prev_query) = prev_query {
134- let prev_entry = & prev_query. cleaner . peek ( ) . registry_entry ;
135- let mut queries_registry = client. queries_registry . write_unchecked ( ) ;
136- // Remove the entry from the previous query
137- queries_registry. remove ( prev_entry) . unwrap ( ) ;
133+ use_sync_memo ( query_keys. clone ( ) , || {
134+ let mut query = query ( ) ;
135+ query. registry_entry . query_keys = query_keys. to_vec ( ) ;
136+
137+ let registry_entry = query. registry_entry ;
138+ let mut queries_registry = client. queries_registry . write_unchecked ( ) ;
139+
140+ // Create a group of listeners for the given [RegistryEntry] key.
141+ let query_listeners =
142+ queries_registry
143+ . entry ( registry_entry. clone ( ) )
144+ . or_insert ( QueryListeners {
145+ listeners : HashSet :: default ( ) ,
146+ value : QueryValue :: new ( RwLock :: new ( CachedResult :: new (
147+ query. initial_value . unwrap_or_default ( ) ,
148+ ) ) ) ,
149+ query_fn : query. query_fn ,
150+ } ) ;
151+
152+ // Register this listener's scope
153+ query_listeners
154+ . listeners
155+ . insert ( current_scope_id ( ) . unwrap ( ) ) ;
156+
157+ let value = query_listeners. value . clone ( ) ;
158+
159+ // Asynchronously initialize the query value
160+ spawn ( {
161+ to_owned ! [ registry_entry] ;
162+ async move {
163+ client. run_new_query ( & registry_entry) . await ;
138164 }
165+ } ) ;
139166
140- let mut query = query ( ) ;
141- query. registry_entry . query_keys = query_keys. to_vec ( ) ;
142-
143- let registry_entry = query. registry_entry ;
144- let mut queries_registry = client. queries_registry . write_unchecked ( ) ;
145-
146- // Create a group of listeners for the given [RegistryEntry] key.
147- let query_listeners =
148- queries_registry
149- . entry ( registry_entry. clone ( ) )
150- . or_insert ( QueryListeners {
151- listeners : HashSet :: default ( ) ,
152- value : QueryValue :: new ( RwLock :: new ( CachedResult :: new (
153- query. initial_value . unwrap_or_default ( ) ,
154- ) ) ) ,
155- query_fn : query. query_fn ,
156- } ) ;
157-
158- // Register this listener's scope
159- query_listeners
160- . listeners
161- . insert ( current_scope_id ( ) . unwrap ( ) ) ;
162-
163- let value = query_listeners. value . clone ( ) ;
164-
165- // Asynchronously initialize the query value
166- spawn ( {
167- to_owned ! [ registry_entry] ;
168- async move {
169- client. run_new_query ( & registry_entry) . await ;
170- }
171- } ) ;
172-
173- UseQuery {
167+ UseQuery {
168+ client,
169+ value,
170+ scope_id : current_scope_id ( ) . unwrap ( ) ,
171+ cleaner : Signal :: new ( UseQueryCleaner {
174172 client,
175- value ,
173+ registry_entry ,
176174 scope_id : current_scope_id ( ) . unwrap ( ) ,
177- cleaner : Signal :: new ( UseQueryCleaner {
178- client,
179- registry_entry,
180- scope_id : current_scope_id ( ) . unwrap ( ) ,
181- } ) ,
182- }
183- } ,
184- )
175+ } ) ,
176+ }
177+ } )
185178}
186179
187180/// Alternative to [use_memo]
188181/// Benefits:
189182/// - No unnecessary rerenders
190- /// - Access to the previous value when dependencies change
191183/// Downsides:
192184/// - T needs to be Clone (cannot be avoided)
193- fn use_memo_with_old_value < T : ' static + Clone , D : PartialEq + ' static > (
185+ fn use_sync_memo < T : ' static + Clone , D : PartialEq + ' static > (
194186 deps : D ,
195- init : impl FnOnce ( Option < T > ) -> T ,
187+ init : impl FnOnce ( ) -> T ,
196188) -> T {
197189 struct Memoized < T , D > {
198190 value : T ,
@@ -207,10 +199,7 @@ fn use_memo_with_old_value<T: 'static + Clone, D: PartialEq + 'static>(
207199 != Some ( & deps) ;
208200
209201 let new_value = if deps_have_changed {
210- let prev_value = memoized_value
211- . take ( )
212- . map ( |memoized_value| memoized_value. value ) ;
213- Some ( init ( prev_value) )
202+ Some ( init ( ) )
214203 } else {
215204 None
216205 } ;
0 commit comments