pub struct Effect<S> { /* private fields */ }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
effectsfeature 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.
Implementations§
Source§impl Effect<LocalStorage>
impl Effect<LocalStorage>
Sourcepub 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.
Sourcepub 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)"Source§impl Effect<SyncStorage>
impl Effect<SyncStorage>
Sourcepub 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.
Sourcepub 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.
Sourcepub 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§
Source§impl<S> ToAnySubscriber for Effect<S>
impl<S> ToAnySubscriber for Effect<S>
Source§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<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<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
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 more