|
@@ -603,39 +603,56 @@ struct SignalSubscriberDrop<T: 'static, S: Storage<SignalData<T>>> {
|
|
origin: &'static std::panic::Location<'static>,
|
|
origin: &'static std::panic::Location<'static>,
|
|
}
|
|
}
|
|
|
|
|
|
-impl<T: 'static, S: Storage<SignalData<T>>> Drop for SignalSubscriberDrop<T, S> {
|
|
|
|
- fn drop(&mut self) {
|
|
|
|
- #[cfg(debug_assertions)]
|
|
|
|
- {
|
|
|
|
- tracing::trace!(
|
|
|
|
- "Write on signal at {} finished, updating subscribers",
|
|
|
|
- self.origin
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- // Check if the write happened during a render. If it did, we should warn the user that this is generally a bad practice.
|
|
|
|
- if dioxus_core::vdom_is_rendering() {
|
|
|
|
- tracing::warn!(
|
|
|
|
- "Write on signal at {} happened while a component was running. Writing to signals during a render can cause infinite rerenders when you read the same signal in the component. Consider writing to the signal in an effect, future, or event handler if possible.",
|
|
|
|
- self.origin
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
|
|
+pub mod warnings {
|
|
|
|
+ //! Warnings that can be triggered by suspicious usage of signals
|
|
|
|
+
|
|
|
|
+ use super::*;
|
|
|
|
+ use ::warnings::warning;
|
|
|
|
+
|
|
|
|
+ /// Check if the write happened during a render. If it did, warn the user that this is generally a bad practice.
|
|
|
|
+ #[warning]
|
|
|
|
+ pub fn signal_write_in_component_body(origin: &'static std::panic::Location<'static>) {
|
|
|
|
+ // Check if the write happened during a render. If it did, we should warn the user that this is generally a bad practice.
|
|
|
|
+ if dioxus_core::vdom_is_rendering() {
|
|
|
|
+ tracing::warn!(
|
|
|
|
+ "Write on signal at {} happened while a component was running. Writing to signals during a render can cause infinite rerenders when you read the same signal in the component. Consider writing to the signal in an effect, future, or event handler if possible.",
|
|
|
|
+ origin
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
- // Check if the write happened during a scope that the signal is also subscribed to. If it did, this will probably cause an infinite loop.
|
|
|
|
- if let Some(reactive_context) = ReactiveContext::current() {
|
|
|
|
- if let Ok(inner) = self.signal.inner.try_read() {
|
|
|
|
- if let Ok(subscribers) = inner.subscribers.lock() {
|
|
|
|
- for subscriber in subscribers.iter() {
|
|
|
|
- if reactive_context == *subscriber {
|
|
|
|
- let origin = self.origin;
|
|
|
|
- tracing::warn!(
|
|
|
|
- "Write on signal at {origin} finished in {reactive_context} which is also subscribed to the signal. This will likely cause an infinite loop. When the write finishes, {reactive_context} will rerun which may cause the write to be rerun again.\nHINT:\n{SIGNAL_READ_WRITE_SAME_SCOPE_HELP}",
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
|
|
+ /// Check if the write happened during a scope that the signal is also subscribed to. If it did, trigger a warning because it will likely cause an infinite loop.
|
|
|
|
+ #[warning]
|
|
|
|
+ pub fn signal_read_and_write_in_reactive_scope<T: 'static, S: Storage<SignalData<T>>>(
|
|
|
|
+ origin: &'static std::panic::Location<'static>,
|
|
|
|
+ signal: Signal<T, S>,
|
|
|
|
+ ) {
|
|
|
|
+ // Check if the write happened during a scope that the signal is also subscribed to. If it did, this will probably cause an infinite loop.
|
|
|
|
+ if let Some(reactive_context) = ReactiveContext::current() {
|
|
|
|
+ if let Ok(inner) = signal.inner.try_read() {
|
|
|
|
+ if let Ok(subscribers) = inner.subscribers.lock() {
|
|
|
|
+ for subscriber in subscribers.iter() {
|
|
|
|
+ if reactive_context == *subscriber {
|
|
|
|
+ tracing::warn!(
|
|
|
|
+ "Write on signal at {origin} finished in {reactive_context} which is also subscribed to the signal. This will likely cause an infinite loop. When the write finishes, {reactive_context} will rerun which may cause the write to be rerun again.\nHINT:\n{SIGNAL_READ_WRITE_SAME_SCOPE_HELP}",
|
|
|
|
+ );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#[allow(clippy::no_effect)]
|
|
|
|
+impl<T: 'static, S: Storage<SignalData<T>>> Drop for SignalSubscriberDrop<T, S> {
|
|
|
|
+ fn drop(&mut self) {
|
|
|
|
+ tracing::trace!(
|
|
|
|
+ "Write on signal at {} finished, updating subscribers",
|
|
|
|
+ self.origin
|
|
|
|
+ );
|
|
|
|
+ warnings::signal_write_in_component_body(self.origin);
|
|
|
|
+ warnings::signal_read_and_write_in_reactive_scope::<T, S>(self.origin, self.signal);
|
|
self.signal.update_subscribers();
|
|
self.signal.update_subscribers();
|
|
}
|
|
}
|
|
}
|
|
}
|