mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-25 05:30:21 +00:00
fix signals
This commit is contained in:
parent
611f0d3b5f
commit
f6fd20bb61
7 changed files with 32 additions and 67 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -2881,11 +2881,17 @@ dependencies = [
|
|||
"dioxus",
|
||||
"dioxus-core",
|
||||
"dioxus-desktop",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"generational-box",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"simple_logger",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3868,6 +3874,8 @@ dependencies = [
|
|||
name = "generational-box"
|
||||
version = "0.4.3"
|
||||
dependencies = [
|
||||
"criterion 0.3.6",
|
||||
"parking_lot",
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
|
|
|
@ -27,14 +27,14 @@ impl<R: Eq + Hash> Comparer<R> {
|
|||
|
||||
if let Some(previous) = previous.take() {
|
||||
if let Some(value) = subscribers.get(&previous) {
|
||||
value.set(false);
|
||||
*value.write_unchecked() = false;
|
||||
}
|
||||
}
|
||||
|
||||
let current = f();
|
||||
|
||||
if let Some(value) = subscribers.get(¤t) {
|
||||
value.set(true);
|
||||
*value.write_unchecked() = true;
|
||||
}
|
||||
|
||||
*previous = Some(current);
|
||||
|
@ -59,14 +59,14 @@ impl<R: Eq + Hash, S: Storage<SignalData<bool>>> Comparer<R, S> {
|
|||
|
||||
if let Some(previous) = previous.take() {
|
||||
if let Some(value) = subscribers.get(&previous) {
|
||||
value.set(false);
|
||||
*value.write_unchecked() = false;
|
||||
}
|
||||
}
|
||||
|
||||
let current = f();
|
||||
|
||||
if let Some(value) = subscribers.get(¤t) {
|
||||
value.set(true);
|
||||
*value.write_unchecked() = true;
|
||||
}
|
||||
|
||||
*previous = Some(current);
|
||||
|
@ -136,6 +136,6 @@ impl<R, S: Storage<SignalData<bool>>> Copy for Comparer<R, S> {}
|
|||
/// }
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn use_comparer<R: Eq + Hash>(cx: &ScopeState, f: impl FnMut() -> R + 'static) -> Comparer<R> {
|
||||
*cx.use_hook(move || Comparer::new(f))
|
||||
pub fn use_comparer<R: Eq + Hash>(f: impl FnMut() -> R + 'static) -> Comparer<R> {
|
||||
use_hook(move || Comparer::new(f))
|
||||
}
|
||||
|
|
|
@ -7,8 +7,7 @@ use parking_lot::RwLock;
|
|||
use rustc_hash::FxHashMap;
|
||||
use std::fmt::{self, Formatter};
|
||||
|
||||
use crate::use_signal;
|
||||
use crate::{dependency::Dependency, CopyValue};
|
||||
use crate::CopyValue;
|
||||
|
||||
thread_local! {
|
||||
pub(crate)static EFFECT_STACK: EffectStack = EffectStack::default();
|
||||
|
|
|
@ -177,42 +177,6 @@ macro_rules! write_impls {
|
|||
self.with_mut(|v| v.split_off(at))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> $ty<Option<T>> {
|
||||
/// Takes the value out of the Option.
|
||||
#[track_caller]
|
||||
pub fn take(&mut self) -> Option<T> {
|
||||
self.with_mut(|v| v.take())
|
||||
}
|
||||
|
||||
/// Replace the value in the Option.
|
||||
#[track_caller]
|
||||
pub fn replace(&mut self, value: T) -> Option<T> {
|
||||
self.with_mut(|v| v.replace(value))
|
||||
}
|
||||
|
||||
/// Gets the value out of the Option, or inserts the given value if the Option is empty.
|
||||
#[track_caller]
|
||||
pub fn get_or_insert(&mut self, default: T) -> GenerationalRef<T> {
|
||||
self.get_or_insert_with(|| default)
|
||||
}
|
||||
|
||||
/// Gets the value out of the Option, or inserts the value returned by the given function if the Option is empty.
|
||||
#[track_caller]
|
||||
pub fn get_or_insert_with(
|
||||
&mut self,
|
||||
default: impl FnOnce() -> T,
|
||||
) -> GenerationalRef<T> {
|
||||
let borrow = self.read();
|
||||
if borrow.is_none() {
|
||||
drop(borrow);
|
||||
self.write_unchecked().replace(default());
|
||||
GenerationalRef::map(self.read(), |v| v.as_ref().unwrap())
|
||||
} else {
|
||||
GenerationalRef::map(borrow, |v| v.as_ref().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -324,23 +288,23 @@ write_impls!(Signal, Storage<SignalData<T>>, Storage<SignalData<Vec<T>>>);
|
|||
|
||||
impl<T: 'static, S: Storage<SignalData<Option<T>>>> Signal<Option<T>, S> {
|
||||
/// Takes the value out of the Option.
|
||||
pub fn take(&self) -> Option<T> {
|
||||
pub fn take(&mut self) -> Option<T> {
|
||||
self.with_mut(|v| v.take())
|
||||
}
|
||||
|
||||
/// Replace the value in the Option.
|
||||
pub fn replace(&self, value: T) -> Option<T> {
|
||||
pub fn replace(&mut self, value: T) -> Option<T> {
|
||||
self.with_mut(|v| v.replace(value))
|
||||
}
|
||||
|
||||
/// Gets the value out of the Option, or inserts the given value if the Option is empty.
|
||||
pub fn get_or_insert(&self, default: T) -> <<S::Ref as Mappable<SignalData<Option<T>>>>::Mapped<Option<T>> as Mappable<Option<T>>>::Mapped<T>{
|
||||
pub fn get_or_insert(&mut self, default: T) -> <<S::Ref as Mappable<SignalData<Option<T>>>>::Mapped<Option<T>> as Mappable<Option<T>>>::Mapped<T>{
|
||||
self.get_or_insert_with(|| default)
|
||||
}
|
||||
|
||||
/// Gets the value out of the Option, or inserts the value returned by the given function if the Option is empty.
|
||||
pub fn get_or_insert_with(
|
||||
&self,
|
||||
&mut self,
|
||||
default: impl FnOnce() -> T,
|
||||
) -><<S::Ref as Mappable<SignalData<Option<T>>>>::Mapped<Option<T>> as Mappable<Option<T>>>::Mapped<T>{
|
||||
let borrow = self.read();
|
||||
|
|
|
@ -23,7 +23,7 @@ fn current_owner<S: Storage<T>, T>() -> Rc<Owner<S>> {
|
|||
Some(rt) => rt,
|
||||
None => {
|
||||
let owner = Rc::new(S::owner());
|
||||
provide_context(owner).expect("in a virtual dom")
|
||||
provide_context(owner)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ fn owner_in_scope<S: Storage<T>, T>(scope: ScopeId) -> Rc<Owner<S>> {
|
|||
Some(rt) => rt,
|
||||
None => {
|
||||
let owner = Rc::new(S::owner());
|
||||
provide_context_to_scope(scope, owner).expect("in a virtual dom")
|
||||
scope.provide_context(owner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ impl<T: 'static, S: Storage<T>> CopyValue<T, S> {
|
|||
self.value.try_write()
|
||||
}
|
||||
|
||||
pub fn write_unchecked(&self) -> GenerationalRefMut<T> {
|
||||
pub fn write_unchecked(&self) -> S::Mut {
|
||||
self.value.write()
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ impl<T: 'static, S: Storage<T>> PartialEq for CopyValue<T, S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, S: Storage<T>> Deref for CopyValue<T, S> {
|
||||
impl<T: Copy, S: Storage<T>> Deref for CopyValue<T, S> {
|
||||
type Target = dyn Fn() -> T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
|
|
@ -72,14 +72,13 @@ pub fn use_maybe_sync_selector<R: PartialEq, S: Storage<SignalData<R>>>(
|
|||
#[track_caller]
|
||||
#[must_use = "Consider using `use_effect` to rerun a callback when dependencies change"]
|
||||
pub fn use_selector_with_dependencies<R: PartialEq, D: Dependency>(
|
||||
cx: &ScopeState,
|
||||
dependencies: D,
|
||||
f: impl FnMut(D::Out) -> R + 'static,
|
||||
) -> ReadOnlySignal<R>
|
||||
where
|
||||
D::Out: 'static,
|
||||
{
|
||||
use_maybe_sync_selector_with_dependencies(cx, dependencies, f)
|
||||
use_maybe_sync_selector_with_dependencies(dependencies, f)
|
||||
}
|
||||
|
||||
/// Creates a new Selector that may be sync with some local dependencies. The selector will be run immediately and whenever any signal it reads or any dependencies it tracks changes
|
||||
|
@ -105,15 +104,14 @@ pub fn use_maybe_sync_selector_with_dependencies<
|
|||
D: Dependency,
|
||||
S: Storage<SignalData<R>>,
|
||||
>(
|
||||
cx: &ScopeState,
|
||||
dependencies: D,
|
||||
mut f: impl FnMut(D::Out) -> R + 'static,
|
||||
) -> ReadOnlySignal<R, S>
|
||||
where
|
||||
D::Out: 'static,
|
||||
{
|
||||
let dependencies_signal = use_signal(cx, || dependencies.out());
|
||||
let selector = *cx.use_hook(|| {
|
||||
let mut dependencies_signal = use_signal(|| dependencies.out());
|
||||
let selector = use_hook(|| {
|
||||
maybe_sync_selector(move || {
|
||||
let deref = &*dependencies_signal.read();
|
||||
f(deref.clone())
|
||||
|
@ -141,7 +139,7 @@ pub fn selector<R: PartialEq>(f: impl FnMut() -> R + 'static) -> ReadOnlySignal<
|
|||
pub fn maybe_sync_selector<R: PartialEq, S: Storage<SignalData<R>>>(
|
||||
mut f: impl FnMut() -> R + 'static,
|
||||
) -> ReadOnlySignal<R, S> {
|
||||
let state = Signal::<R, S> {
|
||||
let mut state = Signal::<R, S> {
|
||||
inner: CopyValue::invalid(),
|
||||
};
|
||||
let effect = Effect {
|
||||
|
@ -154,8 +152,7 @@ pub fn maybe_sync_selector<R: PartialEq, S: Storage<SignalData<R>>>(
|
|||
}
|
||||
state.inner.value.set(SignalData {
|
||||
subscribers: Default::default(),
|
||||
effect_subscribers: Default::default(),
|
||||
update_any: schedule_update_any().expect("in a virtual dom"),
|
||||
update_any: schedule_update_any(),
|
||||
value: f(),
|
||||
effect_ref: get_effect_ref(),
|
||||
});
|
||||
|
|
|
@ -104,13 +104,10 @@ pub fn use_signal<T: 'static>(f: impl FnOnce() -> T) -> Signal<T, UnsyncStorage>
|
|||
/// ```
|
||||
#[must_use]
|
||||
#[track_caller]
|
||||
pub fn use_signal_sync<T: Send + Sync + 'static>(
|
||||
cx: &ScopeState,
|
||||
f: impl FnOnce() -> T,
|
||||
) -> Signal<T, SyncStorage> {
|
||||
pub fn use_signal_sync<T: Send + Sync + 'static>(f: impl FnOnce() -> T) -> Signal<T, SyncStorage> {
|
||||
#[cfg(debug_assertions)]
|
||||
let caller = std::panic::Location::caller();
|
||||
*cx.use_hook(|| {
|
||||
use_hook(|| {
|
||||
Signal::new_with_caller(
|
||||
f(),
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -467,7 +464,7 @@ impl<T: 'static, S: Storage<SignalData<T>>> PartialEq for Signal<T, S> {
|
|||
/// Allow calling a signal with signal() syntax
|
||||
///
|
||||
/// Currently only limited to copy types, though could probably specialize for string/arc/rc
|
||||
impl<T, S: Storage<SignalData<T>> + 'static> Deref for Signal<T, S> {
|
||||
impl<T: Copy, S: Storage<SignalData<T>> + 'static> Deref for Signal<T, S> {
|
||||
type Target = dyn Fn() -> T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
@ -634,7 +631,7 @@ impl<T: 'static, S: Storage<SignalData<T>>> PartialEq for ReadOnlySignal<T, S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, S: Storage<SignalData<T>> + 'static> Deref for ReadOnlySignal<T, S> {
|
||||
impl<T: Copy, S: Storage<SignalData<T>> + 'static> Deref for ReadOnlySignal<T, S> {
|
||||
type Target = dyn Fn() -> T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
|
Loading…
Reference in a new issue