pub fn create_effect<T>(f: impl Fn(Option<T>) -> T + 'static) -> Effect<T>
where T: 'static,
Expand description

Effects run a certain chunk of code whenever the signals they depend on change. create_effect queues the given function to run once, tracks its dependence on any signal 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: don’t write to signals within effects, unless you’re coordinating with some other non-reactive side effect. (If you need to define a signal that depends on the value of other signals, use a derived signal or create_memo).

This first run is queued for the next microtask, i.e., it runs after all other synchronous code has completed. In practical terms, this means that if you use create_effect in the body of the component, it will run after the view has been created and (presumably) mounted. (If you need an effect that runs immediately, use create_render_effect.)

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.

By default, effects do not run on the server. This means you can call browser-specific APIs within the effect function without causing issues. If you need an effect to run on the server, use create_isomorphic_effect.

let (a, set_a) = create_signal(0);
let (b, set_b) = create_signal(0);

// ✅ use effects to interact between reactive state and the outside world
create_effect(move |_| {
  // immediately prints "Value: 0" and subscribes to `a`
  log::debug!("Value: {}", a.get());
});

set_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
create_effect(move |_| {
  // this technically works but can cause unnecessary re-renders
  // and easily lead to problems like infinite loops
  set_b.set(a.get() + 1);
});