Struct Effect
pub struct Effect<S> {
inner: Option<ArenaItem<Option<Arc<RwLock<EffectInner>>>, S>>,
}
Expand description
Effects run a certain chunk of code whenever the signals they depend on change.
Creating an effect runs the given function once after any current synchronous work is done. This tracks its reactive values read within it, and reruns the function whenever the value of a dependency changes.
Effects are intended to run side-effects of the system, not to synchronize state
within the system. In other words: In most cases, you usually should not write to
signals inside effects. (If you need to define a signal that depends on the value of
other signals, use a derived signal or a Memo
).
You can provide an effect function without parameters or one with one parameter.
If you provide such a parameter, the effect function is called with an argument containing
whatever value it returned the last time it ran. On the initial run, this is None
.
Effects stop running when their reactive Owner
is disposed.
ยงExample
let a = RwSignal::new(0);
let b = RwSignal::new(0);
// โ
use effects to interact between reactive state and the outside world
Effect::new(move || {
// on the next โtickโ prints "Value: 0" and subscribes to `a`
println!("Value: {}", a.get());
});
a.set(1);
// โ
because it's subscribed to `a`, the effect reruns and prints "Value: 1"
// โ don't use effects to synchronize state within the reactive system
Effect::new(move || {
// this technically works but can cause unnecessary re-renders
// and easily lead to problems like infinite loops
b.set(a.get() + 1);
});
ยงWeb-Specific Notes
- Scheduling: Effects run after synchronous work, on the next โtickโ of the reactive system. This makes them suitable for โon mountโ actions: they will fire immediately after DOM rendering.
- By default, effects do not run unless the
effects
feature is enabled. If you are using this with a web framework, this generally means that effects do not run on the server. and you can call browser-specific APIs within the effect function without causing issues. If you need an effect to run on the server, useEffect::new_isomorphic
.
Fieldsยง
ยงinner: Option<ArenaItem<Option<Arc<RwLock<EffectInner>>>, S>>
Implementationsยง
ยงimpl Effect<LocalStorage>
impl Effect<LocalStorage>
pub fn new<T, M>(
fun: impl EffectFunction<T, M> + 'static,
) -> Effect<LocalStorage>where
T: 'static,
pub fn new<T, M>(
fun: impl EffectFunction<T, M> + 'static,
) -> Effect<LocalStorage>where
T: 'static,
Creates a new effect, which runs once on the next โtickโ, and then runs again when reactive values that are read inside it change.
This spawns a task on the local thread using
spawn_local
. For an effect that can be spawned on
any thread, use new_sync
.
pub fn watch<D, T>(
dependency_fn: impl FnMut() -> D + 'static,
handler: impl FnMut(&D, Option<&D>, Option<T>) -> T + 'static,
immediate: bool,
) -> Effect<LocalStorage>where
D: 'static,
T: 'static,
pub fn watch<D, T>(
dependency_fn: impl FnMut() -> D + 'static,
handler: impl FnMut(&D, Option<&D>, Option<T>) -> T + 'static,
immediate: bool,
) -> Effect<LocalStorage>where
D: 'static,
T: 'static,
A version of Effect::new
that only listens to any dependency
that is accessed inside dependency_fn
.
The return value of dependency_fn
is passed into handler
as an argument together with the previous value.
Additionally, the last return value of handler
is provided as a third argument, as is done in Effect::new
.
ยงUsage
let (num, set_num) = signal(0);
let effect = Effect::watch(
move || num.get(),
move |num, prev_num, _| {
// log::debug!("Number: {}; Prev: {:?}", num, prev_num);
},
false,
);
set_num.set(1); // > "Number: 1; Prev: Some(0)"
effect.stop(); // stop watching
set_num.set(2); // (nothing happens)
The callback itself doesnโt track any signal that is accessed within it.
let (num, set_num) = signal(0);
let (cb_num, set_cb_num) = signal(0);
Effect::watch(
move || num.get(),
move |num, _, _| {
// log::debug!("Number: {}; Cb: {}", num, cb_num.get());
},
false,
);
set_num.set(1); // > "Number: 1; Cb: 0"
set_cb_num.set(1); // (nothing happens)
set_num.set(2); // > "Number: 2; Cb: 1"
ยงImmediate
If the final parameter immediate
is true, the handler
will run immediately.
If itโs false
, the handler
will run only after
the first change is detected of any signal that is accessed in dependency_fn
.
let (num, set_num) = signal(0);
Effect::watch(
move || num.get(),
move |num, prev_num, _| {
// log::debug!("Number: {}; Prev: {:?}", num, prev_num);
},
true,
); // > "Number: 0; Prev: None"
set_num.set(1); // > "Number: 1; Prev: Some(0)"
ยงimpl Effect<SyncStorage>
impl Effect<SyncStorage>
pub fn new_sync<T, M>(
fun: impl EffectFunction<T, M> + Send + Sync + 'static,
) -> Effect<SyncStorage>
pub fn new_sync<T, M>( fun: impl EffectFunction<T, M> + Send + Sync + 'static, ) -> Effect<SyncStorage>
Creates a new effect, which runs once on the next โtickโ, and then runs again when reactive values that are read inside it change.
This spawns a task that can be run on any thread. For an effect that will be spawned on
the current thread, use new
.
pub fn new_isomorphic<T, M>(
fun: impl EffectFunction<T, M> + Send + Sync + 'static,
) -> Effect<SyncStorage>
pub fn new_isomorphic<T, M>( fun: impl EffectFunction<T, M> + Send + Sync + 'static, ) -> Effect<SyncStorage>
Creates a new effect, which runs once on the next โtickโ, and then runs again when reactive values that are read inside it change.
This will run whether the effects
feature is enabled or not.
pub fn watch_sync<D, T>(
dependency_fn: impl FnMut() -> D + Send + Sync + 'static,
handler: impl FnMut(&D, Option<&D>, Option<T>) -> T + Send + Sync + 'static,
immediate: bool,
) -> Effect<SyncStorage>
pub fn watch_sync<D, T>( dependency_fn: impl FnMut() -> D + Send + Sync + 'static, handler: impl FnMut(&D, Option<&D>, Option<T>) -> T + Send + Sync + 'static, immediate: bool, ) -> Effect<SyncStorage>
This is to Effect::watch
what Effect::new_sync
is to Effect::new
.
Trait Implementationsยง
ยงimpl<S> ToAnySubscriber for Effect<S>
impl<S> ToAnySubscriber for Effect<S>
ยงfn to_any_subscriber(&self) -> AnySubscriber
fn to_any_subscriber(&self) -> AnySubscriber
impl<S> Copy for Effect<S>where
S: Copy,
Auto Trait Implementationsยง
impl<S> Freeze for Effect<S>
impl<S> RefUnwindSafe for Effect<S>
impl<S> Send for Effect<S>
impl<S> Sync for Effect<S>
impl<S> Unpin for Effect<S>
impl<S> UnwindSafe for Effect<S>
Blanket Implementationsยง
Sourceยงimpl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
Sourceยงfn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
Sourceยงfn adapt_into(self) -> D
fn adapt_into(self) -> D
ยงimpl<T> ArchivePointee for T
impl<T> ArchivePointee for T
ยงtype ArchivedMetadata = ()
type ArchivedMetadata = ()
ยงfn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Sourceยงimpl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
Sourceยงfn arrays_from(colors: C) -> T
fn arrays_from(colors: C) -> T
Sourceยงimpl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
Sourceยงfn arrays_into(self) -> C
fn arrays_into(self) -> C
Sourceยงimpl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Sourceยงfn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Sourceยงimpl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
Sourceยงtype Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
parameters
when converting.Sourceยงfn cam16_into_unclamped(
self,
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> T
fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Sourceยงimpl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Sourceยงimpl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
Sourceยงfn components_from(colors: C) -> T
fn components_from(colors: C) -> T
ยงimpl<F, W, T, D> Deserialize<With<T, W>, D> for F
impl<F, W, T, D> Deserialize<With<T, W>, D> for F
ยงfn deserialize(
&self,
deserializer: &mut D,
) -> Result<With<T, W>, <D as Fallible>::Error>
fn deserialize( &self, deserializer: &mut D, ) -> Result<With<T, W>, <D as Fallible>::Error>
ยงimpl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
ยงfn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
, which can then be
downcast
into Box<dyn ConcreteType>
where ConcreteType
implements Trait
.ยงfn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
, which can then be further
downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.ยงfn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
โs vtable from &Trait
โs.ยงfn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
โs vtable from &mut Trait
โs.ยงimpl<T> DowncastSend for T
impl<T> DowncastSend for T
ยงimpl<T> DowncastSync for T
impl<T> DowncastSync for T
Sourceยงimpl<T> FromAngle<T> for T
impl<T> FromAngle<T> for T
Sourceยงfn from_angle(angle: T) -> T
fn from_angle(angle: T) -> T
angle
.Sourceยงimpl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
Sourceยงfn from_stimulus(other: U) -> T
fn from_stimulus(other: U) -> T
other
into Self
, while performing the appropriate scaling,
rounding and clamping.ยงimpl<T> Instrument for T
impl<T> Instrument for T
ยงfn instrument(self, span: Span) -> Instrumented<Self> โ
fn instrument(self, span: Span) -> Instrumented<Self> โ
Sourceยงimpl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
Sourceยงfn into_angle(self) -> U
fn into_angle(self) -> U
T
.Sourceยงimpl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
Sourceยงtype Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
parameters
when converting.Sourceยงfn into_cam16_unclamped(
self,
parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>,
) -> T
fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Sourceยงimpl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
Sourceยงfn into_color(self) -> U
fn into_color(self) -> U
Sourceยงimpl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
Sourceยงfn into_color_unclamped(self) -> U
fn into_color_unclamped(self) -> U
Sourceยงimpl<T> IntoEither for T
impl<T> IntoEither for T
Sourceยงfn into_either(self, into_left: bool) -> Either<Self, Self> โ
fn into_either(self, into_left: bool) -> Either<Self, Self> โ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSourceยงfn into_either_with<F>(self, into_left: F) -> Either<Self, Self> โ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> โ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSourceยงimpl<T> IntoStimulus<T> for T
impl<T> IntoStimulus<T> for T
Sourceยงfn into_stimulus(self) -> T
fn into_stimulus(self) -> T
self
into T
, while performing the appropriate scaling,
rounding and clamping.ยงimpl<T> Pointable for T
impl<T> Pointable for T
ยงimpl<T> Pointee for T
impl<T> Pointee for T
ยงimpl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
ยงimpl<T> SerializableKey for T
impl<T> SerializableKey for T
ยงimpl<T> StorageAccess<T> for T
impl<T> StorageAccess<T> for T
ยงfn as_borrowed(&self) -> &T
fn as_borrowed(&self) -> &T
ยงfn into_taken(self) -> T
fn into_taken(self) -> T
Sourceยงimpl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
Sourceยงtype Error = <C as TryFromComponents<T>>::Error
type Error = <C as TryFromComponents<T>>::Error
try_into_colors
fails to cast.Sourceยงfn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
Sourceยงimpl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
Sourceยงfn try_into_color(self) -> Result<U, OutOfBounds<U>>
fn try_into_color(self) -> Result<U, OutOfBounds<U>>
OutOfBounds
error is returned which contains
the unclamped color. Read more