leptos_reactive/lib.rs
1#![forbid(unsafe_code)]
2#![deny(missing_docs)]
3#![cfg_attr(feature = "nightly", feature(fn_traits))]
4#![cfg_attr(feature = "nightly", feature(unboxed_closures))]
5#![cfg_attr(feature = "nightly", feature(type_name_of_val))]
6#![cfg_attr(feature = "nightly", feature(auto_traits))]
7#![cfg_attr(feature = "nightly", feature(negative_impls))]
8// to prevent warnings from popping up when a nightly feature is stabilized
9#![allow(stable_features)]
10
11//! The reactive system for the [Leptos](https://docs.rs/leptos/latest/leptos/) Web framework.
12//!
13//! ## Fine-Grained Reactivity
14//!
15//! Leptos is built on a fine-grained reactive system, which means that individual reactive values
16//! (“signals,” sometimes known as observables) trigger the code that reacts to them (“effects,”
17//! sometimes known as observers) to re-run. These two halves of the reactive system are inter-dependent.
18//! Without effects, signals can change within the reactive system but never be observed in a way
19//! that interacts with the outside world. Without signals, effects run once but never again, as
20//! there’s no observable value to subscribe to.
21//!
22//! Here are the most commonly-used functions and types you'll need to build a reactive system:
23//!
24//! ### Signals
25//! 1. *Signals:* [`create_signal`], which returns a ([`ReadSignal`],
26//! [`WriteSignal`] tuple, or [`create_rw_signal`], which returns
27//! a signal [`RwSignal`] without this read-write segregation.
28//! 2. *Derived Signals:* any function that relies on another signal.
29//! 3. *Memos:* [`create_memo`], which returns a [`Memo`].
30//! 4. *Resources:* [`create_resource`], which converts an `async` [`Future`](std::future::Future) into a
31//! synchronous [`Resource`] signal.
32//! 5. *Triggers:* [`create_trigger`], creates a purely reactive [`Trigger`] primitive without any associated state.
33//!
34//! ### Effects
35//! 1. Use [`create_effect`] when you need to synchronize the reactive system
36//! with something outside it (for example: logging to the console, writing to a file or local storage)
37//! 2. The Leptos DOM renderer wraps any [`Fn`] in your template with [`create_effect`], so
38//! components you write do *not* need explicit effects to synchronize with the DOM.
39//!
40//! ### Example
41//! ```
42//! use leptos_reactive::*;
43//!
44//! // creates a new reactive runtime
45//! // this is omitted from most of the examples in the docs
46//! // you usually won't need to call it yourself
47//! let runtime = create_runtime();
48//! // a signal: returns a (getter, setter) pair
49//! let (count, set_count) = create_signal(0);
50//!
51//! // calling the getter gets the value
52//! // can be `count()` on nightly
53//! assert_eq!(count.get(), 0);
54//! // calling the setter sets the value
55//! // can be `set_count(1)` on nightly
56//! set_count.set(1);
57//! // or we can mutate it in place with update()
58//! set_count.update(|n| *n += 1);
59//!
60//! // a derived signal: a plain closure that relies on the signal
61//! // the closure will run whenever we *access* double_count()
62//! let double_count = move || count.get() * 2;
63//! assert_eq!(double_count(), 4);
64//!
65//! // a memo: subscribes to the signal
66//! // the closure will run only when count changes
67//! let memoized_triple_count = create_memo(move |_| count.get() * 3);
68//! // can be `memoized_triple_count()` on nightly
69//! assert_eq!(memoized_triple_count.get(), 6);
70//!
71//! // this effect will run whenever `count` changes
72//! create_effect(move |_| {
73//! println!("Count = {}", count.get());
74//! });
75//!
76//! // disposes of the reactive runtime
77//! runtime.dispose();
78//! ```
79
80#[cfg_attr(any(debug_assertions, feature = "ssr"), macro_use)]
81extern crate tracing;
82
83#[macro_use]
84mod signal;
85pub mod callback;
86mod context;
87#[macro_use]
88mod diagnostics;
89mod effect;
90mod hydration;
91// contains "private" implementation details right now.
92// could make this unhidden in the future if needed.
93// macro_export makes it public from the crate root anyways
94#[doc(hidden)]
95pub mod macros;
96mod memo;
97mod node;
98mod resource;
99mod runtime;
100mod selector;
101#[cfg(any(doc, feature = "serde"))]
102mod serde;
103mod serialization;
104mod signal_wrappers_read;
105mod signal_wrappers_write;
106mod slice;
107mod spawn;
108mod spawn_microtask;
109mod stored_value;
110pub mod suspense;
111mod trigger;
112mod watch;
113
114pub use callback::*;
115pub use context::*;
116pub use diagnostics::SpecialNonReactiveZone;
117pub use effect::*;
118pub use hydration::{FragmentData, SharedContext};
119pub use memo::*;
120pub use node::Disposer;
121pub use oco::*;
122pub use oco_ref as oco;
123pub use resource::*;
124use runtime::*;
125pub use runtime::{
126 as_child_of_current_owner, batch, create_runtime, current_runtime,
127 on_cleanup, run_as_child, set_current_runtime,
128 spawn_local_with_current_owner, spawn_local_with_owner, try_batch,
129 try_spawn_local_with_current_owner, try_spawn_local_with_owner,
130 try_with_owner, untrack, untrack_with_diagnostics, with_current_owner,
131 with_owner, Owner, RuntimeId, ScopedFuture,
132};
133pub use selector::*;
134pub use serialization::*;
135pub use signal::{prelude as signal_prelude, *};
136pub use signal_wrappers_read::*;
137pub use signal_wrappers_write::*;
138pub use slice::*;
139pub use spawn::*;
140pub use spawn_microtask::*;
141pub use stored_value::*;
142pub use suspense::{GlobalSuspenseContext, SuspenseContext};
143pub use trigger::*;
144pub use watch::*;
145
146#[doc(hidden)]
147pub fn console_warn(s: &str) {
148 cfg_if::cfg_if! {
149 if #[cfg(all(target_arch = "wasm32", any(feature = "csr", feature = "hydrate")))] {
150 web_sys::console::warn_1(&wasm_bindgen::JsValue::from_str(s));
151 } else {
152 eprintln!("{s}");
153 }
154 }
155}