Struct freya::prelude::ReactiveContext

pub struct ReactiveContext { /* private fields */ }
Expand description

§Reactivity

The core of dioxus relies on the concept of reactivity. Reactivity is the system that updates your app when state changes.

There are two parts to reactivity: Reactive Contexts and Tracked Values.

§Reactive Contexts

Reactive Contexts keep track of what state different parts of your app rely on. Reactive Context show up throughout dioxus: Component, use_effect, use_memo and use_resource all have their own reactive contexts:

let count = use_signal(|| 0);
// The reactive context in the memo knows that the memo depends on the count signal
use_memo(move || count() * 2);

§Tracked Values

Tracked values are values that reactive contexts know about. When you read a tracked value, the reactive context will rerun when the value changes. Signals, Memos, and Resources are all tracked values:

// The count signal is tracked
let count = use_signal(|| 0);
// When you read the count signal, the reactive context subscribes to the count signal
let double_count = use_memo(move || count() * 2);

§Reactivity

Reactivity is the system that combines reactive context and tracked values to update your app when state changes.

You can use reactivity to create derived state and update your app when state changes.

You can derive state from other state with use_memo.

use dioxus::prelude::*;

let mut count = use_signal(|| 0);
let double_count = use_memo(move || count() * 2);

// Now whenever we read double_count, we know it is always twice the value of count
println!("{}", double_count); // Prints "2"

// After we write to count, the reactive context will rerun and double_count will be updated automatically
count += 1;

println!("{}", double_count); // Prints "4"

You can also use reactivity to create derive state asynchronously. For example, you can use use_resource to load data from a server:

use dioxus::prelude::*;

let count = use_signal(|| 0);
let double_count = use_resource(move || async move {
    // Start a request to the server. We are reading the value of count to format it into the url
    // Since we are reading count, this resource will "subscribe" to changes to count (when count changes, the resource will rerun)
    let response = reqwest::get(format!("https://myserver.com/doubleme?count={count}")).await.unwrap();
    response.text().await.unwrap()
});

§Non Reactive State

You can use plain Rust types in Dioxus, but you should be aware that they are not reactive. If you read the non-reactive state, reactive scopes will not subscribe to the state.

You can make non-reactive state reactive by using the Signal type instead of a plain Rust type or by using the use_reactive hook.

use dioxus::prelude::*;

// ❌ Don't create non-reactive state
let state = use_hook(|| std::cell::RefCell::new(0));

// Computed values will get out of date if the state they depend on is not reactive
let doubled = use_memo(move || *state.borrow() * 2);

// ✅ Create reactive state
let state = use_signal(|| 0);

// Computed values will automatically keep up to date with the latest reactive state
let doubled = use_memo(move || state() * 2);

// ❌ Don't depend on non-reactive prop state in memos/resources
#[component]
fn MyComponent(state: i32) -> Element {
    let doubled = use_memo(move || state * 2);
    todo!()
}

// ✅ Wrap your props in ReadOnlySignal to make them reactive
#[component]
fn MyReactiveComponent(state: ReadOnlySignal<i32>) -> Element {
    let doubled = use_memo(move || state() * 2);
    todo!()
}

If your state can’t be reactive, you can use the use_reactive hook to make it reactive.

use dioxus::prelude::*;

let state = rand::random::<i32>();

// You can make the state reactive by wrapping it in use_reactive
let doubled = use_memo(use_reactive!(|state| state * 2));

Implementations§

§

impl ReactiveContext

pub fn new() -> (ReactiveContext, UnboundedReceiver<()>)

Create a new reactive context

pub fn new_with_origin( origin: &'static Location<'static> ) -> (ReactiveContext, UnboundedReceiver<()>)

Create a new reactive context with a location for debugging purposes This is useful for reactive contexts created within closures

pub fn new_with_callback( callback: impl FnMut() + Send + Sync + 'static, scope: ScopeId, origin: &'static Location<'static> ) -> ReactiveContext

Create a new reactive context that may update a scope. When any signal that this context subscribes to changes, the callback will be run

pub fn current() -> Option<ReactiveContext>

Get the current reactive context from the nearest reactive hook or scope

pub fn clear_subscribers(&self)

Clear all subscribers to this context

pub fn reset_and_run_in<O>(&self, f: impl FnOnce() -> O) -> O

Reset the reactive context and then run the callback in the context. This can be used to create custom reactive hooks like use_memo.

fn use_simplified_memo(mut closure: impl FnMut() -> i32 + 'static) -> Signal<i32> {
    use_hook(|| {
        // Create a new reactive context and channel that will receive a value every time a value the reactive context subscribes to changes
        let (reactive_context, mut changed) = ReactiveContext::new();
        // Compute the value of the memo inside the reactive context. This will subscribe the reactive context to any values you read inside the closure
        let value = reactive_context.reset_and_run_in(&mut closure);
        // Create a new signal with the value of the memo
        let mut signal = Signal::new(value);
        // Create a task that reruns the closure when the reactive context changes
        spawn(async move {
            while changed.next().await.is_some() {
                // Since we reset the reactive context as we run the closure, our memo will only subscribe to the new values that are read in the closure
                let new_value = reactive_context.run_in(&mut closure);
                if new_value != value {
                    signal.set(new_value);
                }
            }
        });
        signal
    })
}

let mut boolean = use_signal(|| false);
let mut count = use_signal(|| 0);
// Because we use `reset_and_run_in` instead of just `run_in`, our memo will only subscribe to the signals that are read this run of the closure (initially just the boolean)
let memo = use_simplified_memo(move || if boolean() { count() } else { 0 });
println!("{memo}");
// Because the count signal is not read in this run of the closure, the memo will not rerun
count += 1;
println!("{memo}");
// Because the boolean signal is read in this run of the closure, the memo will rerun
boolean.toggle();
println!("{memo}");
// If we toggle the boolean again, and the memo unsubscribes from the count signal
boolean.toggle();
println!("{memo}");

pub fn run_in<O>(&self, f: impl FnOnce() -> O) -> O

Run this function in the context of this reactive context

This will set the current reactive context to this context for the duration of the function. You can then get information about the current subscriptions.

pub fn mark_dirty(&self) -> bool

Marks this reactive context as dirty

If there’s a scope associated with this context, then it will be marked as dirty too

Returns true if the context was marked as dirty, or false if the context has been dropped

pub fn subscribe(&self, subscriptions: Arc<Mutex<HashSet<ReactiveContext>>>)

Subscribe to this context. The reactive context will automatically remove itself from the subscriptions when it is reset.

pub fn origin_scope(&self) -> ScopeId

Get the scope that inner CopyValue is associated with

Trait Implementations§

§

impl Clone for ReactiveContext

§

fn clone(&self) -> ReactiveContext

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Display for ReactiveContext

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Hash for ReactiveContext

§

fn hash<H>(&self, state: &mut H)
where H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
§

impl PartialEq for ReactiveContext

§

fn eq(&self, other: &ReactiveContext) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
§

impl Copy for ReactiveContext

§

impl Eq for ReactiveContext

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> CallHasher for T
where T: Hash + ?Sized,

§

fn get_hash<H, B>(value: &H, build_hasher: &B) -> u64
where H: Hash + ?Sized, B: BuildHasher,

§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &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)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

§

type Output = T

Should always be Self
§

impl<Ret> SpawnIfAsync<(), Ret> for Ret

§

fn spawn(self) -> Ret

Spawn the value into the dioxus runtime if it is an async block
§

impl<T, O> SuperFrom<T> for O
where O: From<T>,

§

fn super_from(input: T) -> O

Convert from a type to another type.
§

impl<T, O, M> SuperInto<O, M> for T
where O: SuperFrom<T, M>,

§

fn super_into(self) -> O

Convert from a type to another type.
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> ToSmolStr for T
where T: Display + ?Sized,

§

fn to_smolstr(&self) -> SmolStr

source§

impl<T> ToString for T
where T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<Cfg> TryIntoConfig for Cfg

§

fn into_config(self, config: &mut Option<Cfg>)

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> CloneAny for T
where T: Any + Clone,

§

impl<T> DependencyElement for T
where T: 'static + PartialEq + Clone,