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
sourceimpl<'a> Scope<'a>
impl<'a> Scope<'a>
sourcepub fn provide_context<T>(&'a self, value: T) where
T: 'static,
pub fn provide_context<T>(&'a self, value: T) where
T: 'static,
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.
sourcepub fn provide_context_ref<T>(&'a self, value: &'a T) where
T: 'static,
pub fn provide_context_ref<T>(&'a self, value: &'a T) where
T: 'static,
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.
sourcepub fn try_use_context<T>(&'a self) -> Option<&'a T> where
T: 'static,
pub fn try_use_context<T>(&'a self) -> Option<&'a T> where
T: 'static,
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
.
sourcepub fn use_context<T>(&'a self) -> &'a T where
T: 'static,
pub fn use_context<T>(&'a self) -> &'a T where
T: 'static,
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
.
sourcepub fn scope_depth(&self) -> u32
pub fn scope_depth(&self) -> u32
Returns the current depth of the scope. If the scope is the root scope, returns 0
.
sourceimpl<'a> Scope<'a>
impl<'a> Scope<'a>
sourcepub fn create_effect(&self, f: impl FnMut() + 'a)
pub fn create_effect(&self, f: impl FnMut() + 'a)
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"
sourcepub fn create_effect_scoped<F>(&'a self, f: F) where
F: 'a + for<'child_lifetime> FnMut(BoundedScopeRef<'child_lifetime, 'a>),
pub fn create_effect_scoped<F>(&'a self, f: F) where
F: 'a + for<'child_lifetime> FnMut(BoundedScopeRef<'child_lifetime, 'a>),
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.
});
sourceimpl<'a> Scope<'a>
impl<'a> Scope<'a>
sourcepub fn map_keyed<T, K, U>(
&'a self,
list: &'a ReadSignal<Vec<T, Global>>,
map_fn: impl for<'child_lifetime> Fn(BoundedScopeRef<'child_lifetime, 'a>, T) -> U + 'a,
key_fn: impl Fn(&T) -> K + 'a
) -> &'a ReadSignal<Vec<U, Global>> where
T: 'a + Eq + Clone,
K: Eq + Hash,
U: 'a + Clone,
pub fn map_keyed<T, K, U>(
&'a self,
list: &'a ReadSignal<Vec<T, Global>>,
map_fn: impl for<'child_lifetime> Fn(BoundedScopeRef<'child_lifetime, 'a>, T) -> U + 'a,
key_fn: impl Fn(&T) -> K + 'a
) -> &'a ReadSignal<Vec<U, Global>> where
T: 'a + Eq + Clone,
K: Eq + Hash,
U: 'a + Clone,
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 aReadSignal
(obtained from aSignal
) 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
sourcepub fn map_indexed<T, U>(
&'a self,
list: &'a ReadSignal<Vec<T, Global>>,
map_fn: impl for<'child_lifetime> Fn(BoundedScopeRef<'child_lifetime, 'a>, T) -> U + 'a
) -> &'a ReadSignal<Vec<U, Global>> where
T: PartialEq<T> + Clone,
U: 'a + Clone,
pub fn map_indexed<T, U>(
&'a self,
list: &'a ReadSignal<Vec<T, Global>>,
map_fn: impl for<'child_lifetime> Fn(BoundedScopeRef<'child_lifetime, 'a>, T) -> U + 'a
) -> &'a ReadSignal<Vec<U, Global>> where
T: PartialEq<T> + Clone,
U: 'a + Clone,
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 aReadSignal
(obtained from aSignal
) and therefore reactive.map_fn
- A closure that maps from the input type to the output type.
sourceimpl<'a> Scope<'a>
impl<'a> Scope<'a>
sourcepub fn create_memo<U>(&'a self, f: impl FnMut() -> U + 'a) -> &'a ReadSignal<U> where
U: 'a,
pub fn create_memo<U>(&'a self, f: impl FnMut() -> U + 'a) -> &'a ReadSignal<U> where
U: 'a,
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);
sourcepub fn create_selector<U>(
&'a self,
f: impl FnMut() -> U + 'a
) -> &'a ReadSignal<U> where
U: 'a + PartialEq<U>,
pub fn create_selector<U>(
&'a self,
f: impl FnMut() -> U + 'a
) -> &'a ReadSignal<U> where
U: 'a + PartialEq<U>,
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);
sourcepub fn create_selector_with<U>(
&'a self,
f: impl FnMut() -> U + 'a,
eq_f: impl Fn(&U, &U) -> bool + 'a
) -> &'a ReadSignal<U> where
U: 'a,
pub fn create_selector_with<U>(
&'a self,
f: impl FnMut() -> U + 'a,
eq_f: impl Fn(&U, &U) -> bool + 'a
) -> &'a ReadSignal<U> where
U: 'a,
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
.
sourcepub fn create_reducer<U, Msg>(
&'a self,
initial: U,
reduce: impl Fn(&U, Msg) -> U + 'a
) -> (&'a ReadSignal<U>, impl Fn(Msg) + 'a)
pub fn create_reducer<U, Msg>(
&'a self,
initial: U,
reduce: impl Fn(&U, Msg) -> U + 'a
) -> (&'a ReadSignal<U>, impl Fn(Msg) + 'a)
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);
sourceimpl<'a> Scope<'a>
impl<'a> Scope<'a>
sourcepub fn create_signal<T>(&'a self, value: T) -> &'a Signal<T>
pub fn create_signal<T>(&'a self, value: T) -> &'a Signal<T>
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);
});
sourcepub fn create_ref<T>(&'a self, value: T) -> &'a T where
T: 'a,
pub fn create_ref<T>(&'a self, value: T) -> &'a T where
T: 'a,
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();
sourcepub fn on_cleanup(&self, f: impl FnOnce() + 'a)
pub fn on_cleanup(&self, f: impl FnOnce() + 'a)
Adds a callback that is called when the scope is destroyed.
sourcepub fn create_child_scope<F>(&'a self, f: F) -> ScopeDisposer<'a> where
F: for<'child_lifetime> FnOnce(BoundedScopeRef<'child_lifetime, 'a>),
pub fn create_child_scope<F>(&'a self, f: F) -> ScopeDisposer<'a> where
F: for<'child_lifetime> FnOnce(BoundedScopeRef<'child_lifetime, 'a>),
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.
sourcepub fn use_scope_status(&self) -> RcSignal<bool>
pub fn use_scope_status(&self) -> RcSignal<bool>
Returns a RcSignal
that is true
when the scope is still valid and false
once it is
disposed.
Trait Implementations
sourceimpl<'a> ScopeCreateNodeRef<'a> for Scope<'a>
impl<'a> ScopeCreateNodeRef<'a> for Scope<'a>
sourcefn create_node_ref<G: GenericNode>(&'a self) -> &'a NodeRef<G>
fn create_node_ref<G: GenericNode>(&'a self) -> &'a NodeRef<G>
sourceimpl<'a> ScopeFuturesExt<'a> for Scope<'a>
impl<'a> ScopeFuturesExt<'a> for Scope<'a>
fn create_resource<U, F>(&'a self, f: F) -> RcSignal<Option<U>> where
U: 'static,
F: Future<Output = U> + 'static,
sourceimpl<'a> ScopeMotionExt<'a> for Scope<'a>
impl<'a> ScopeMotionExt<'a> for Scope<'a>
sourcefn create_raf(
&'a self,
f: impl FnMut() + 'a
) -> (RcSignal<bool>, &'a dyn Fn(), &'a dyn Fn())
fn create_raf(
&'a self,
f: impl FnMut() + 'a
) -> (RcSignal<bool>, &'a dyn Fn(), &'a dyn Fn())
Schedule a callback to be called on each animation frame.
Does nothing if not on wasm32
target. Read more
sourceimpl<'a> ScopeSpawnFuture<'a> for Scope<'a>
impl<'a> ScopeSpawnFuture<'a> for Scope<'a>
sourcepub fn spawn_future(&'a self, f: impl Future<Output = ()> + 'a)
pub fn spawn_future(&'a self, f: impl Future<Output = ()> + 'a)
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
impl<'a> !RefUnwindSafe for Scope<'a>
impl<'a> !Send for Scope<'a>
impl<'a> !Sync for Scope<'a>
impl<'a> Unpin for Scope<'a>
impl<'a> !UnwindSafe for Scope<'a>
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcepub fn borrow_mut(&mut self) -> &mut T
pub fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more