pub struct Scope<'a> { /* private fields */ }
Expand description

A reactive scope.

The only way to ever use a scope should be behind a reference. It should never be possible to access a raw Scope on the stack.

The intended way to access a Scope is with the create_scope function.

For convenience, the ScopeRef type alias is defined as a reference to a Scope.

Lifetime

  • 'a - The lifetime of the scope and all data allocated on it. This allows passing in data from an outer scope into an inner scope. This lifetime is also invariant because it is used within an cell.

Implementations

Provides a context in the current Scope. The context can later be accessed by using use_context lower in the scope hierarchy.

The context can also be accessed in the same scope in which it is provided.

This method is simply a wrapper around create_ref and provide_context_ref.

Panics

This method panics if a context with the same type exists already in this scope. Note that if a context with the same type exists in a parent scope, the new context will shadow the old context.

Provides a context in the current Scope. The context can later be accessed by using use_context lower in the scope hierarchy.

The context can also be accessed in the same scope in which it is provided.

Unlike provide_context, this method accepts a reference that lives at least as long as the scope.

Panics

This method panics if a context with the same type exists already in this scope. Note that if a context with the same type exists in a parent scope, the new context will shadow the old context.

Tries to get a context value of the given type. If no context with the right type found, returns None. For a panicking version, see use_context.

Gets a context value of the given type.

Panics

This method panics if the context cannot be found in the current scope hierarchy. For a non-panicking version, see try_use_context.

Returns the current depth of the scope. If the scope is the root scope, returns 0.

Creates an effect on signals used inside the effect closure.

Example
let state = ctx.create_signal(0);

ctx.create_effect(|| {
    println!("State changed. New state value = {}", state.get());
}); // Prints "State changed. New state value = 0"

state.set(1); // Prints "State changed. New state value = 1"

Creates an effect on signals used inside the effect closure.

Instead of create_effect, this function also provides a new reactive scope instead the effect closure. This scope is created for each new run of the effect.

Items created within the scope cannot escape outside the effect because that can result in an use-after-free.

Example
ctx.create_effect_scoped(|ctx| {
    // Use the scoped ctx inside here.
    let _nested_signal = ctx.create_signal(0);
    // _nested_signal cannot escape out of the effect closure.
});

Function that maps a Vec to another Vec via a map function. The mapped Vec is lazy computed, meaning that it’s value will only be updated when requested. Modifications to the input Vec are diffed using keys to prevent recomputing values that have not changed.

This function is the underlying utility behind Keyed.

Params
  • list - The list to be mapped. The list must be a ReadSignal (obtained from a Signal) and therefore reactive.
  • map_fn - A closure that maps from the input type to the output type.
  • key_fn - A closure that returns an unique key to each entry.

Credits: Based on TypeScript implementation in https://github.com/solidjs/solid

Function that maps a Vec to another Vec via a map function. The mapped Vec is lazy computed, meaning that it’s value will only be updated when requested. Modifications to the input Vec are diffed by index to prevent recomputing values that have not changed.

Generally, it is preferred to use map_keyed instead when a key function is available.

This function is the underlying utility behind Indexed.

Params
  • list - The list to be mapped. The list must be a ReadSignal (obtained from a Signal) and therefore reactive.
  • map_fn - A closure that maps from the input type to the output type.

Creates a memoized computation from some signals. The output is derived from all the signals that are used within the memo closure. If any of the tracked signals are updated, the memo is also updated.

Difference from derived signals

Derived signals (functions referencing signals) are lazy and do not keep track of the result of the computation. This means that the computation will not be executed until needed. This also means that calling the derived signal twice will result in the same computation twice.

let state = ctx.create_signal(0);
let double = || *state.get() * 2;

let _ = double();
// Here, the closure named double is called again.
// If the computation is expensive enough, this would be wasted work!
let _ = double();

Memos, on the other hand, are eagerly evaluated and will only run the computation when one of its dependencies change.

Memos also incur a slightly higher performance penalty than simple derived signals.

Example
let state = ctx.create_signal(0);
let double = ctx.create_memo(|| *state.get() * 2);

assert_eq!(*double.get(), 0);
state.set(1);
assert_eq!(*double.get(), 2);

Creates a memoized value from some signals. Unlike create_memo, this function will not notify dependents of a change if the output is the same. That is why the output of the function must implement PartialEq.

To specify a custom comparison function, use create_selector_with.

Example
let state = ctx.create_signal(0);
let double = ctx.create_selector(|| *state.get() * 2);

assert_eq!(*double.get(), 0);
state.set(1);
assert_eq!(*double.get(), 2);

Creates a memoized value from some signals. Unlike create_memo, this function will not notify dependents of a change if the output is the same.

It takes a comparison function to compare the old and new value, which returns true if they are the same and false otherwise.

To use the type’s PartialEq implementation instead of a custom function, use create_selector.

An alternative to create_signal that uses a reducer to get the next value.

It uses a reducer function that takes the previous value and a message and returns the next value.

Returns a ReadSignal and a dispatch function to send messages to the reducer.

Params
  • initial - The initial value of the state.
  • reducer - A function that takes the previous value and a message and returns the next value.
Example
enum Msg {
    Increment,
    Decrement,
}

let (state, dispatch) = ctx.create_reducer(0, |state, msg: Msg| match msg {
    Msg::Increment => *state + 1,
    Msg::Decrement => *state - 1,
});

assert_eq!(*state.get(), 0);
dispatch(Msg::Increment);
assert_eq!(*state.get(), 1);
dispatch(Msg::Decrement);
assert_eq!(*state.get(), 0);

Create a new Signal under the current Scope. The created signal lasts as long as the scope and cannot be used outside of the scope.

Signal lifetime

The lifetime of the returned signal is the same as the Scope. As such, the signal cannot escape the Scope.

let mut outer = None;
create_scope_immediate(|ctx| {
    let signal = ctx.create_signal(0);
    outer = Some(signal);
});

Allocate a new arbitrary value under the current Scope. The allocated value lasts as long as the scope and cannot be used outside of the scope.

Ref lifetime

The lifetime of the returned ref is the same as the Scope. As such, the reference cannot escape the Scope.

let mut outer = None;
let disposer = ctx.create_child_scope(|ctx| {
    let data = ctx.create_ref(0);
    let raw: &i32 = &data;
    outer = Some(raw);
    //           ^^^
});
disposer();
let _ = outer.unwrap();

Adds a callback that is called when the scope is destroyed.

Create a child scope.

Returns a disposer function which will release the memory owned by the Scope. If the disposer function is never called, the child scope will be disposed automatically when the parent scope is disposed.

Child scope lifetime

The lifetime of the child scope is strictly a subset of the lifetime of the parent scope.

[------------'a-------------]
     [---------'b--------]
'a: lifetime of parent
'b: lifetime of child

If the disposer is never called, the lifetime 'b lasts as long as 'a. As such, it is impossible for anything allocated in the child scope to escape into the parent scope.

let mut outer = None;
let disposer = ctx.create_child_scope(|ctx| {
    outer = Some(ctx);
    //           ^^^
});
disposer();
let _ = outer.unwrap();

However, the closure itself only needs to live as long as the call to this method because it is called immediately. For example, the following compiles and is perfectly safe:

let mut outer = String::new();
let disposer = ctx.create_child_scope(|ctx| {
    // outer is accessible inside the closure.
    outer = "Hello World!".to_string();
});
unsafe { disposer.dispose(); }
drop(outer);
//   ^^^^^ -> and remains accessible outside the closure.

Returns a RcSignal that is true when the scope is still valid and false once it is disposed.

Trait Implementations

Executes the destructor for this type. Read more

Create a new NodeRef on the current Scope.

Schedule a callback to be called on each animation frame. Does nothing if not on wasm32 target. Read more

Schedule a callback to be called on each animation frame. Does nothing if not on wasm32 target. Read more

Create a new Tweened signal.

Spawns a !Send future on the current scope. If the scope is destroyed before the future is completed, it is aborted immediately. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.