Get Started
Installation
cargo add leptos-use
Examples
Usage Example
Simply import the functions you need from leptos-use
use leptos::*;
use leptos_use::{use_mouse, UseMouseReturn};
#[component]
fn Demo() -> impl IntoView {
let UseMouseReturn { x, y, .. } = use_mouse();
view! { cx,
{x} " x " {y}
}
}
Please refer to the functions list for more details.
Stable Rust
Just like leptos
this library can be safely run on stable rust.
In the Getting Started section
of the leptos
docs you can read more about what this means.
Options
Most functions in Leptos-Use come with a version ..._with_options
. For example use_css_var
has a
version use_css_var_with_options
. As the name suggests, you can provide additional options to those versions of the
functions.
These options are defined as structs with the corresponding PascalCase name. For our example use_css_var_with_options
the name of the struct is UseCssVarOptions
. Every option struct implements Default
and the builder pattern to
make it easy to change only the values needed. This can look like the following example.
#![allow(unused)] fn main() { let (color, set_color) = use_css_var_with_options( "--color", UseCssVarOptions::default() .target(el) .initial_value("#eee"), ); }
Here only the values target
and initial_value
are changed and everything else is left to default.
TODO : automatic conversion like Fn and Option
Element Parameters
Many functions in this library operate on HTML/SVG elements. For example, the
function use_element_size
returns the width and height of an element:
#![allow(unused)] fn main() { use leptos::{*, html::Div}; use leptos_use::{use_element_size, UseElementSizeReturn}; #[component] pub fn Component() -> impl IntoView { let el = create_node_ref::<Div>(); let UseElementSizeReturn { width, height } = use_element_size(el); view! { <div node_ref=el></div> } } }
In the example above we used a Leptos NodeRef
to pass into the function. But that is not
the only way you can do that. All of these work as well:
#![allow(unused)] fn main() { use_element_size(window().body()); // Option<web_sys::Element> use_element_size(window().body().unwrap()); // web_sys::Element use_element_size("div > p.some-class"); // &str or String intepreted as CSS selector pub fn some_directive(el: HtmlElement<AnyElement>) { use_element_size(el); // leptos::html::HtmlElement<T> } }
Signal of Strings: Signal<String>
, ReadSignal<String>
, RwSignal<String>
, Memo<String>
; also works with &str
:
#![allow(unused)] fn main() { let (str_signal, set_str_signal) = create_signal("div > p.some-class".to_string()); use_element_size(str_signal); }
Signals of Elements: Signal<web_sys::Element>
, ReadSignal<web_sys::Element>
, RwSignal<web_sys::Element>
, Memo<web_sys::Element>
; also works with Option<web_sys::Element>
:
#![allow(unused)] fn main() { let (el_signal, set_el_signal) = create_signal(document().query_selector("div > p.some-class").unwrap()); use_element_size(el_signal); }
How it works
Looking at the source code of use_element_size
you'll find sth like
#![allow(unused)] fn main() { pub fn use_element_size(el: Into<ElementMaybeSignal<...>>) -> UseElementSizeReturn {} }
All the above code works because there are From
implementations for all of these
types for ElementMaybeSignal
.
ElementsMaybeSignal
Some functions work on one or more elements. Take use_resize_observer
for example.
This works very much the same way as described above but instead of Into<ElementMaybeSignal>
it takes an Into<ElementsMaybeSignal>
(note the plural). This means you can use it exactly in
the same ways as you saw with the singular ElementMaybeSignal
. Only this time, when you use
String
or &str
it will be interpreted as CSS selector with query_selector_all
.
But you can also use it with containers.
#![allow(unused)] fn main() { // Array of Option<web_sys::Element> use_resize_observer([window().body(), document().query_selector("div > p.some-class").unsrap()]); // Vec of &str. All of them will be interpreted as CSS selectors with query_selector_all() and the // results will be merged into one Vec. use_resize_observer(vec!["div > p.some-class", "p.some-class"]); // Slice of NodeRef let node_ref1 = create_node_ref::<Div>(); let node_ref2 = create_node_ref::<Div>(); use_resize_observer(vec![node_ref1, node_ref2].as_slice()); }
Usage in Options
Some functions have options that take Element(s)MaybeSignal
.
They can be used in the same way.
#![allow(unused)] fn main() { use_mouse_with_options( UseMouseOptions::default().target("div > p.some-class") ); }
See also "Excluding Elements" in on_click_outside
.
Server-Side Rendering
When using together with server-side rendering (SSR) you have to enable the feature ssr
similar to
how you do it for leptos
.
In your Cargo.toml file enable Leptos-Use's ssr
feature only from your project's ssr
feature:
[dependencies]
leptos-use = "0.10" # do NOT enable the "ssr" feature here
...
[features]
hydrate = [
"leptos/hydrate",
...
]
ssr = [
...
"leptos/ssr",
...
"leptos-use/ssr" # <== add this
]
...
Please see the ssr
example in the examples folder
for a simple working demonstration.
Many functions work differently on the server and on the client. If that's the case you will find information about these differences in their respective docs under the section "Server-Side Rendering". If you don't find that section, it means that the function works exactly the same on both, the client and the server.
Do not enable the
ssr
feature directly!Don't do the following.
[dependencies] leptos-use = { version = "0.10", features = ["ssr"] } # this is wrong
The ssr
feature is used to select which version of the functions are built.
Effectively it means your application is built two times: with ssr
enabled to
build the server executable, and with ssr
disabled to build the client's WASM
binary module.
So if you enable leptos-use
's ssr
feature globally, you will get the server
version of the functions in the client.
By adding "leptos-use/ssr"
to the ssr
feature of your project, it will only
be enabled when your project is built with ssr
, and you will get the server
functions server-side, and the client functions client-side.
WASM on the server
If you enable ssr
in your project on a wasm32
target architecture, you will get
a compile-time warning in the console because it is a common mistake that users enable ssr
globally.
If you're using wasm32
on the server however you can safely disable this warning by
enabling the wasm_ssr
feature together with ssr
.
Functions with Target Elements
A lot of functions like use_resize_observer
and use_element_size
are only useful when a target HTML/SVG element is
available. This is not always the case on the server. If you use them with NodeRefs
they will just work in SSR.
But what if you want to use them with window()
or document()
?
To enable that we provide the helper functions use_window()
and use_document()
which return
a new-type-wrapped Option<web_sys::Window>
or Option<web_sys::Document>
respectively. These can be
used safely on the server. The following code works on both the client and the server:
#![allow(unused)] fn main() { use leptos::*; use leptos::ev::keyup; use leptos_use::{use_event_listener, use_window}; use_event_listener(use_window(), keyup, | evt| { ... }); }
There are some convenience methods provided as well, like use_document().body()
which
just propagate a None
on the server.
Encoding and Decoding Data
Several functions encode and decode data for storing it and/or sending it over the network. To do this, codecs
from the crate codee
are used. They
implement the traits Encoder
with the
method encode
and Decoder
with the
method decode
.
There are two types of codecs: One that encodes as binary data (Vec[u8]
) and another type that encodes as
strings (String
). There is also an adapter
Base64
that can be used to
wrap a binary codec and make it a string codec by representing the binary data as a base64 string.
Please check the documentation of codee
for more details and a list of all
available codecs.
Example
In this example, a codec is given to use_cookie
that stores data as a string in the JSON
format. Since cookies can only store strings, we have to use string codecs here.
use leptos::*;
use leptos_use::use_cookie;
use serde::{Deserialize, Serialize};
use codee::string::JsonCodec;
#[component]
pub fn App(cx: Scope) -> impl IntoView {
#[derive(Serialize, Deserialize, Clone)]
struct MyState {
chicken_count: i32,
egg_count: i32,
}
let (cookie, set_cookie) = use_cookie::<MyState, JsonCodec>("my-state-cookie");
view! {}
}
Custom Codecs
If you don't find a suitable codec for your needs, you can implement your own; it's straightforward!
If you want to create a string codec, you can look at
JsonSerdeCodec
.
In case it's a binary codec, have a look at
BincodeSerdeCodec
.
Versioning
For a discussion on how to implement versioning please refer to the
relevant section in the docs for codee
.
Changelog
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.13.10] - 2024-11-14
- Fixed potential SSR crash in
use_locale(s)
(thanks to @veigaribo)
[0.13.9] - 2024-11-10
- Reverted use_user_media to have video enabled by default
- Fixed exponential increase on websocket reconnects
[0.13.8] - 2024-11-06
- Backported fixes from 0.14.0-rc1
[0.13.7] - 2024-10-20
- Added video and audio options to
use_user_media
(thanks to @sauloco). - Fixed cookies in SSR (thanks to @jim-taylor-business).
[0.13.6] - 2024-10-20
- Updated leptos-spin version to 0.2 (thanks to @tqq1994516).
[0.13.5] - 2024-09-15
New Function π
use_textarea_autosize
[0.13.4] - 2024-09-05
Fix π
use_websocket
now returns a signal for the websocket instance so the user can actually use it. Before it always returnedNone
.
[0.13.3] - 2024-09-02
Fix π
- Fixed
use_color_mode
with cookies enabled
[0.13.2] - 2024-09-02
Fix π
- Fixed web-sys
unstable_apis
flag foruse_web_lock
[0.13.1] - 2024-09-01
New Functions π
use_web_lock
use_window_size
Change π₯
UseWebsocket::protocols
now supports a signal. It is read right beforeopen
is called. (thanks to @zakstucke)
[0.13.0] - 2024-08-28
New Functions π
use_toggle
use_prefers_reduced_motion
(thanks to @hcandelaria)
Breaking Changes π
use_websocket
now supports different types for sending and receiving messagesSyncSignalOptions
now can take now either transformations or assignment functions but not both.- updated to
codee
version 0.2.0
Fixes π
use_websocket
fixed error with cleanup and reconnect (thanks to @BakerNet).
New Features π
- There is now a feature for almost every function to get better compile and rust-analyzer times.
use_web_notification
now supports thevibrate
option (thanks to @hcandelaria).UseDocument
now supports a whole bunch of methods more fromdocument
(thanks to @luckynumberke7in).
[0.12.0] - 2024-08-14
Make sure you also update
cargo-leptos
to the latest version if you use that.
Breaking Changes π
- Updated to web_sys 0.3.70 which unfortunately is breaking some things.
use_clipboard
doesn't need the unstable flags anymore.use_locale
now usesunic_langid::LanguageIdentifier
and proper locale matching (thanks to @mondeja).- Removed
UseMouseEventExtractorDefault
and reworkedUseMouseCoordType
(thanks to @carloskiki) use_preferred_dark
anduse_color_mode
now try to read theSec-CH-Prefers-Color-Scheme
header in SSR. This brings the necessity to enable an additional feature for them (axum
/actix
/spin
).
Fixes π
- Fixed the codec chapter in the book to refer to crate
codee
.
[0.11.4] - 2024-08-12
New Features π
use_web_notification
now supports the optionsrenotify
,silent
andimage
(thanks to @hcandelaria).sync_signal
no supports the optionsassign_ltr
andassign_rtl
.
[0.11.3] - 2024-07-31
Fix π
- Made
use_timeout_fn
SSR-safe
[0.11.2] - 2024-07-30
Change π₯
use_locale
has now a supported locale list.
(yanked) [0.11.1] - 2024-07-28
New Functions π
use_locale
(thanks to @BrandonDyer64)use_locales
(thanks to @BrandonDyer64)header
β Standard implementations for reading a header on the server.
[0.11.0] - 2024-07-27
New Functions π
use_user_media
New Features π
-
Codecs:
- All codecs now live in their own crate
codee
- There are now binary codecs in addition to string codecs.
FromToBytesCodec
WebpackSerdeCodec
BincodeSerdeCodec
ProstCodec
(see also the section "Breaking Changes π " below)
- Every binary codec can be used as a string codec with the
Base64
wrapper which encodes the binary data as a base64 string.- This required feature
base64
- It can be wrapped for example like this:
Base64<WebpackSerdeCodec>
.
- This required feature
- There is now an
OptionCodec
wrapper that allows to wrap any string codec that encodesT
to encodeOption<T>
.- Use it like this:
OptionCodec<FromToStringCodec<f64>>
.
- Use it like this:
- All codecs now live in their own crate
-
ElementMaybeSignal
is now implemented forwebsys::HtmlElement
(thanks to @blorbb). -
UseStorageOptions
now hasdelay_during_hydration
which has to be used when you conditionally show parts of the DOM controlled by a value from storage. This leads to hydration errors which can be fixed by setting this new option totrue
. -
cookie::SameSite
is now re-exported -
Changing the signal returned by
use_cookie
now tries and changes the headers during SSR. -
New book chapter about codecs
-
The macro
use_derive_signal!
is now exported (thanks to @mscofield0).
Breaking Changes π
UseStorageOptions
andUseEventSourceOptions
no longer accept acodec
value because this is already provided as a generic parameter to the respective function calls.- Codecs have been refactored. There are now two traits that codecs implement:
Encoder
andDecoder
. The traitStringCodec
is gone. The methods are now associated methods and their params now always take references.JsonCodec
has been renamed toJsonSerdeCodec
.- The feature to enable this codec is now called
json_serde
instead of justserde
. ProstCodec
now encodes as binary data. If you want to keep using it with string data you can wrap it like this:Base64<ProstCodec>
.- All of these structs, traits and features now live in their own crate called
codee
- A bunch of new codecs are available. Have a look at the docs for crate
codee
.
use_websocket
:UseWebsocketOptions
has been renamed toUseWebSocketOptions
(uppercase S) to be consistent with the return type.UseWebSocketOptions::reconnect_limit
andUseEventSourceOptions::reconnect_limit
is nowReconnectLimit
instead ofu64
. UseReconnectLimit::Infinite
for infinite retries orReconnectLimit::Limited(...)
for limited retries.use_websocket
now uses codecs to send typed messages over the network.- When calling you have give type parameters for the message type and the
codec:
use_websocket::<String, WebpackSerdeCodec>
- You can use binary or string codecs.
- The
UseWebSocketReturn::send
closure now takes a&T
which is encoded using the codec. - The
UseWebSocketReturn::message
signal now returns anOption<T>
which is decoded using the codec. UseWebSocketReturn::send_bytes
andUseWebSocketReturn::message_bytes
are gone.UseWebSocketOptions::on_message
andUseWebSocketOptions::on_message_bytes
have been renamed toon_message_raw
andon_message_raw_bytes
.- The new
UseWebSocketOptions::on_message
takes a&T
. UseWebSocketOptions::on_error
now takes aUseWebSocketError
instead of aweb_sys::Event
.
- When calling you have give type parameters for the message type and the
codec:
use_storage
now always saves the default value to storage if the key doesn't exist yet.- Renamed
BreakpointsSematic
toBreakpointsSemantic
andbreakpoints_sematic
tobreakpoints_semantic
(note then
) (thanks to @mondeja).
Fixes π
- Fixed auto-reconnect in
use_websocket
- Fixed typo in compiler error messages in
use_cookie
(thanks to @SleeplessOne1917). - Fixed potential signal out of scope issue with
use_raf_fn
Other Changes π₯
- Better links in docs that work both in the book and in rustdoc (thanks to @mondeja).
- Better CI/CD (thanks to @EstebanBorai).
[0.10.10] - 2024-05-10
Change π₯
- Added compile-time warning when you use
ssr
feature withwasm32
. You can enablewasm_ssr
to remove the warning.
[0.10.9] - 2024-04-27
Fixes π
- Fixed
use_color_mode
without cookies and make cookies sync properly with local storage - Fixed
use_infinite_scroll
edge case bug with disposed signals
[0.10.8] - 2024-04-19
Change π₯
use_cookie
now supports Spin out of the box (thanks to @javierEd).
[0.10.7] - 2024-04-10
New Function π
sync_signal
Change π₯
use_color_mode
now supports cookies.
[0.10.6] - 2024-04-02
Fixes π
- Corrected docs of
use_cookie
'smax-age
unit to milliseconds (thanks to @sify21). - Fixed setting multiple cookies in the browser (thanks to @sbking).
[0.10.5] - 2024-03-12
Fix π
- Fixed SSR detection from an url query parameter for
use_color_mode
(thanks to @mondeja).
[0.10.4] - 2024-03-05
New Functions π
use_event_source
Changes π₯
- Wrapped callbacks in a non-reactive zone to remove potential warnings.
- Updated SSR chapter in the book to make it more clear and beginner-friendly (thanks to @flupke).
[0.10.3] - 2024-02-23
New Functions π
use_or
use_and
use_not
Fix π
- Removed signal warnings from
use_websocket
'ssend...
methods.
Changes π₯
use_color_mode
now supports detection from an url query parameter. (thanks to @mondeja)
[0.10.2] - 2024-02-09
New Functions π
use_permission
use_clipboard
use_timeout_fn
[0.10.1] - 2024-01-31
Fix π
- Fixed docs.rs build
[0.10.0] - 2024-01-31
New Functions π
use_broadcast_channel
use_cookie
(thanks to @rakshith-ravi)use_mouse_in_element
use_device_orientation
(thanks to @mondeja)use_device_pixel_ratio
(thanks to @mondeja)use_element_bounding
Breaking Changes π
- The
leptos
version is now 0.6 - The trait
Codec
has been renamed toStringCodec
and has been moved toutil::StringCodec
.- The struct
StringCodec
has been renamed toFromToStringCodec
and has been moved toutil::FromToStringCodec
. - The structs
JsonCodec
andProstCodec
have been moved toutil
as well.
- The struct
- The function
use_storage
now requires type parameters for the stored type and the codec like all the other...storage...
functions.
Fixes π
- Fixed
use_geolocation
SSR compile issue - Fixed
use_intl_number_format
maximum fraction digits option
Changes π₯
- The
UseMouseReturn
signalsx
,y
, andsource_type
are now of typeSignal<f64>
instead ofReadSignal<f64>
. - You can now convert
leptos::html::HtmlElement<T>
intoElement(s)MaybeSignal
. This should make functions a lot easier to use in directives. - There's now a chapter in the book especially for
Element(s)MaybeSignal
. - Throttled or debounced callbacks (in watch__ or __fn) no longer are called after the containing scope was cleaned up.
- The document returned from
use_document
now supports the methodsquery_selector
andquery_selector_all
.
[0.9.0] - 2023-12-06
New Functions π
use_display_media
(thanks to @seanaye)
Breaking Changes π
- (@feral-dot-io) The use
use_<type>_storage
functions have been rewritten to useCodec
s instead of always requiringserde
.- This also removes the feature
storage
- By default the
StringCodec
is used which relies on types implementingFromString + ToString
- If you want to use
JsonCodec
you have to enable the featureserde
- If you want to use
ProstCodec
(new!) you have to enable the featureprost
.
- This also removes the feature
- (@feral-dot-io) The Rust flag
--cfg=web_sys_unstable_apis
is not needed anymore since relevantweb_sys
APIs are now stable. This affects in particularuse_element_size
use_resize_observer
Fixes π
use_raf_fn
anduse_timestamp
no longer spam warnings because ofget
ting signals outside of reactive contexts.use_infinite_scroll
no longer calls the callback twice for the same eventuse_scroll
now usestry_get_untracked
in the debounced callback to avoid panics if the context has been destroyed while the callback was waiting to be called.use_idle
works properly now (no more idles too early).use_web_notification
doesn't panic on the server anymore.
[0.8.2] - 2023-11-09
Fixes π
- Fixed SSR for
- use_timestamp
- use_raf_fn
- use_idle
[0.8.1] - 2023-10-28
Fixes π
- Using strings for
ElementMaybeSignal
andElementsMaybeSignal
is now SSR safe.- This fixes specifically
use_color_mode
to work on the server.
- This fixes specifically
[0.8.0] - 2023-10-24
New Functions π
use_web_notification
(thanks to @centershocks44)use_infinite_scroll
use_service_worker
(thanks to @lpotthast)
Breaking Changes π
use_scroll
returnsimpl Fn(T) + Clone
instead ofBox<dyn Fn(T)>
.
Other Changes π₯
UseScrollReturn
is now documented
[0.7.2] - 2023-10-21
Fixes π
- Some functions still used
window()
which could lead to panics in SSR. This is now fixed. Specifically foruse_draggable
.
[0.7.1] - 2023-10-02
New Function π
use_sorted
[0.7.0] - 2023-09-30
New Functions π
use_timestamp
use_idle
use_document
use_window
use_geolocation
signal_debounced
signal_throttled
Breaking Changes π
- Leptos version is now 0.5
- No
cx: Scope
params are supported/needed anymore because of the changes in Leptos. Please check the release notes of Leptos 0.5 for how to upgrade. watch
is now deprecated in favor ofleptos::watch
and will be removed in a future release.watch_with_options
will continue to exist.use_event_listener_with_options
now takes aUseEventListenerOptions
instead of aweb_sys::AddEventListenerOptions
.use_mutation_observer_with_options
now takes aUseMutationObserverOptions
instead of aweb_sys::MutationObserverInit
.use_websocket
:- takes now a
&str
instead of aString
as itsurl
parameter. - same for the returned
send
method. - The
ready_state
return type is now renamed toConnectionReadyState
instead ofUseWebSocketReadyState
. - The returned signals
ready_state
,message
,message_bytes
have now the typeSignal<...>
instead ofReadSignal<...>
to make them more consistent with other functions. - The options
reconnect_limit
andreconnect_interval
now take au64
instead ofOption<u64>
to improve DX. - The option
manual
has been renamed toimmediate
to make it more consistent with other functions. To port please note thatimmediate
is the inverse ofmanual
(immediate
=!manual
). - Added documentation how pass it ergonomically as context.
- takes now a
use_color_mode
:- The optional
on_changed
handler parameters have changed slightly. Please refer to the docs for more details.
- The optional
- Throttled or debounced functions cannot be
FnOnce
anymore. - All traits
ClonableFn...
have been removed.
Other Changes π₯
use_websocket
can use relative urls now- Callbacks in options don't require to be cloneable anymore
- Callback in
use_raf_fn
doesn't require to be cloneable anymore - All (!) functions can now be safely called on the server. Specifically this includes the following that before
panicked on the server:
use_scroll
use_event_listener
use_element_hover
on_click_outside
use_drop_zone
use_element_size
use_element_visibility
use_resize_observer
use_intersection_observer
use_mutation_observer
Fixes π
use_element_visibility
didn't work in some cases on Chrome properly. This has been fixed.
[0.6.3] - 2023-08-12
Fixes π
use_websocket
panicked after unmount
[0.6.2] - 2023-08-03
Fixes π
use_event_listener_with_options
removes the handlers now correctly.
[0.6.1] - 2023-08-03
Fixes π
use_storage
now uses.get_untracked()
to avoid warnings.
[0.6.0] - 2023-07-17
New Functions π
use_draggable
use_to_string
is_err
is_ok
is_none
is_some
use_raf_fn
Breaking Changes π
- The following functions now accept a
MaybeRwSignal
as their initial/default value which means you can use a synchronizedRwSignal
in those places.use_color_mode
use_cycle_list
use_favicon
use_storage
use_local_storage
use_session_storage
- Instead of returning
ReadSignal
, the following functions now returnSignal
.use_color_mode
use_favicon
use_storage
use_local_storage
use_session_storage
Fixes π
use_drop_zone
now uses.get_untracked()
in event handlers
[0.5.0] - 2023-07-15
New Functions π
use_drop_zone
use_websocket
(thanks @sectore)use_intl_number_format
Changes π₯
- Crate is ready for Server-Side Rendering. Enable feature
ssr
like you do forleptos
.
[0.4.1] - 2023-07-07
New Functions π
use_window_focus
use_window_scroll
use_document_visibility
[0.4.0] - 2023-07-03
Breaking Changes π
- Required
leptos
version is now 0.4 - Following the changes in
leptos
there is no longer astable
crate feature required in order to use this library with a stable toolchain. If you want to use it with a nightly toolchain you have to enable thenightly
feature only onleptos
directly. No change is required forleptos-use
itself.
[0.3.3] - 2023-06-24
New Functions π
use_color_mode
use_cycle_list
use_active_element
Changes π₯
- You can now use this crate with the
stable
toolchain (thanks @lpotthast) - Set leptos dependency to
default-features = false
in order to enable SSR.
[0.3.2] - 2023-06-17
New Functions π
use_css_var
use_element_hover
[0.3.1] - 2023-06-15
New Functions π
use_interval_fn
use_interval
[0.3.0] - 2023-06-13
Breaking Changes π
use_event_listener
no longer returns aBox<dyn Fn()>
but aimpl Fn() + Clone
Changes π₯
- You can now specify a
&str
orSignal<String>
with CSS selectors wherever a node ref is accepted - Callbacks of the following functions no longer require
Clone
use_resize_observer
use_intersection_observer
- These functions now also accept multiple target elements in addition to a single one:
use_resize_observer
use_intersection_observer
New Functions π
whenever
use_mutation_observer
use_abs
on_click_outside
[0.2.1] - 2023-06-11
New Functions
use_intersection_observer
use_element_visibility
[0.2.0] - 2023-06-11
Breaking Changes
watch
doesn't acceptimmediate
as a direct argument anymore. This is only provided by the option variant.watch
has now variantwatch_with_options
which allows for debouncing and throttling.
New Functions
use_storage
use_local_storage
use_session_storage
watch_debounced
watch_throttled
watch_pausable
use_ceil
use_round
use_media_query
use_preferred_dark
use_preferred_contrast
use_favicon
use_breakpoints
Other Changes
- Function count badge in readme
[0.1.8/9] - 2023-06-05
- Fixed documentation and doc tests running for functions behind
#[cfg(web_sys_unstable_apis)]
[0.1.7] - 2023-06-05
New Function
use_element_size
[0.1.6] - 2023-06-03
Changes
- Fixed documentation so all feature are documented
[0.1.5] - 2023-06-03
New Functions
use_floor
use_max
use_min
Changes
- New feature:
math
that has to be activated in order to use the math functions.
[0.1.4] - 2023-06-02
New Functions
use_supported
use_resize_observer
watch
use_mouse
Changes
- Use the crate
default-struct-builder
to provide ergonimic function options.
[0.1.3] - 2023-05-28
New Functions
use_scroll
use_debounce_fn
Other Changes
- Better and more beautiful demo integration into the guide.
Functions
Storage
- use_local_storage β Reactive LocalStorage.
- use_session_storage β Reactive SessionStorage.
- use_storage β Reactive Storage.
Elements
- use_active_element β Reactive
document.activeElement
- use_document β SSR safe
document()
. - use_document_visibility β Reactively track
document.visibilityState
- use_draggable β Make elements draggable.
- use_drop_zone β Create a zone where files can be dropped.
- use_element_bounding β Reactive bounding box of an HTML element
- use_element_size β Reactive size of an HTML element.
- use_element_visibility β Tracks the visibility of an element within the viewport.
- use_intersection_observer β Reactive IntersectionObserver.
- use_mouse_in_element β Reactive mouse position related to an element.
- use_mutation_observer β Reactive MutationObserver.
- use_resize_observer β Reports changes to the dimensions of an Element's content or the border-box.
- use_window β SSR safe
window()
. - use_window_focus β Reactively track window focus
- use_window_scroll β Reactive window scroll.
- use_window_size β Reactive window size.
Browser
- use_breakpoints β Reactive viewport breakpoints.
- use_broadcast_channel β Reactive BroadcastChannel API.
- use_clipboard β Reactive Clipboard API.
- use_color_mode β Reactive color mode (dark / light / customs) with auto data persistence.
- use_cookie β SSR-friendly and reactive cookie access.
- use_css_var β Manipulate CSS variables.
- use_display_media β Reactive
mediaDevices.getDisplayMedia
streaming. - use_event_listener β Use EventListener with ease.
- use_favicon β Reactive favicon.
- use_media_query β Reactive Media Query.
- use_permission β Reactive Permissions API.
- use_preferred_contrast β Reactive prefers-contrast media query.
- use_preferred_dark β Reactive dark theme preference.
- use_prefers_reduced_motion β Reactive reduced motions preference.
- use_service_worker β Reactive ServiceWorker API.
- use_textarea_autosize β Automatically update the height of a textarea depending on the content.
- use_user_media β Reactive
mediaDevices.getUserMedia
streaming. - use_web_lock β Rustified Web Locks API.
- use_web_notification β Reactive Notification API.
Intl
- use_intl_number_format β Reactive
Intl.NumberFormat
. - use_locale β Reactive locale matching.
- use_locales β Reactive locales.
Sensors
- on_click_outside β Listen for clicks outside of an element.
- use_device_orientation β Reactive DeviceOrientationEvent.
- use_device_pixel_ratio β Reactive
window.devicePixelRatio
- use_element_hover β Reactive element's hover state.
- use_geolocation β Reactive Geolocation API.
- use_idle β ///
- use_infinite_scroll β Infinite scrolling of the element.
- use_mouse β Reactive mouse position
- use_scroll β We have to check if the scroll amount is close enough to some threshold in order to
Network
- use_event_source β Reactive EventSource
- use_websocket β Creating and managing a Websocket connection.
Animation
- use_interval β Reactive counter increases on every interval.
- use_interval_fn β Wrapper for
set_interval
with controls. - use_raf_fn β Call function on every requestAnimationFrame.
- use_timeout_fn β Wrapper for
setTimeout
with controls. - use_timestamp β Reactive current timestamp.
Watch
- watch_debounced β A debounced version of [
watch
]. - watch_pausable β Pausable [
watch
]. - watch_throttled β A throttled version of
leptos::watch
. - watch_with_options β A version of
leptos::watch
but with additional options. - whenever β Shorthand for watching a signal to be
true
.
Utilities
Math
- use_abs β Reactive
abs()
. - use_and β Reactive
AND
condition. - use_ceil β Reactive
ceil()
. - use_floor β Reactive
floor()
. - use_max β Reactive
max()
. - use_min β Reactive
min()
. - use_not β Reactive
NOT
condition. - use_or β Reactive
OR
condition. - use_round β Reactive
round()
.
use_local_storage
Reactive LocalStorage.
LocalStorage stores data in the browser with no expiration time. Access is given to all pages from the same origin (e.g., all pages from "https://example.com" share the same origin). While data doesn't expire the user can view, modify and delete all data stored. Browsers allow 5MB of data to be stored.
This is contrast to fn@crate::storage::use_session_storage
which clears data when the page session ends and is not shared.
Usage
See fn@crate::storage::use_storage
for more details on how to use.
Feature
This function is only available if the crate feature
storage
is enabled
Source
use_session_storage
Reactive SessionStorage.
SessionStorages stores data in the browser that is deleted when the page session ends. A page session ends when the browser closes the tab. Data is not shared between pages. While data doesn't expire the user can view, modify and delete all data stored. Browsers allow 5MB of data to be stored.
Use fn@crate::storage::use_local_storage
to store data that is shared amongst all pages with the same origin and persists between page sessions.
Usage
See fn@crate::storage::use_storage
for more details on how to use.
Feature
This function is only available if the crate feature
storage
is enabled
Source
use_storage
Reactive Storage.
The function returns a triplet (read_signal, write_signal, delete_from_storage_fn)
.
Demo
Usage
Pass a StorageType
to determine the kind of key-value browser storage to use.
The specified key is where data is stored. All values are stored as UTF-16 strings which
is then encoded and decoded via the given *Codec
. This value is synced with other calls using
the same key on the same page and across tabs for local storage.
See UseStorageOptions
to see how behavior can be further customised.
Values are (en)decoded via the given codec. You can use any of the string codecs or a
binary codec wrapped in Base64
.
Please check the codec chapter to see what codecs are available and what feature flags they require.
Example
use leptos::*;
use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage};
use serde::{Deserialize, Serialize};
use codee::string::{FromToStringCodec, JsonSerdeCodec, Base64};
use codee::binary::ProstCodec;
#[component]
pub fn Demo() -> impl IntoView {
// Binds a struct:
let (state, set_state, _) = use_local_storage::<MyState, JsonSerdeCodec>("my-state");
// Binds a bool, stored as a string:
let (flag, set_flag, remove_flag) = use_session_storage::<bool, FromToStringCodec>("my-flag");
// Binds a number, stored as a string:
let (count, set_count, _) = use_session_storage::<i32, FromToStringCodec>("my-count");
// Binds a number, stored in JSON:
let (count, set_count, _) = use_session_storage::<i32, JsonSerdeCodec>("my-count-kept-in-js");
// Bind string with SessionStorage stored in ProtoBuf format:
let (id, set_id, _) = use_storage::<String, Base64<ProstCodec>>(
StorageType::Session,
"my-id",
);
view! { }
}
// Data stored in JSON must implement Serialize, Deserialize.
// And you have to add the feature "serde" to your project's Cargo.toml
#[derive(Serialize, Deserialize, Clone, PartialEq)]
pub struct MyState {
pub hello: String,
pub greeting: String,
}
// Default can be used to implement initial or deleted values.
// You can also use a signal via UseStorageOptions::default_value`
impl Default for MyState {
fn default() -> Self {
Self {
hello: "hi".to_string(),
greeting: "Hello".to_string()
}
}
}
Server-Side Rendering
On the server the returned signals will just read/manipulate the initial_value
without persistence.
Hydration bugs and use_cookie
If you use a value from storage to control conditional rendering you might run into issues with hydration.
use leptos::*;
use leptos_use::storage::use_session_storage;
use codee::string::FromToStringCodec;
#[component]
pub fn Example() -> impl IntoView {
let (flag, set_flag, _) = use_session_storage::<bool, FromToStringCodec>("my-flag");
view! {
<Show when=move || flag.get()>
<div>Some conditional content</div>
</Show>
}
}
You can see hydration warnings in the browser console and the conditional parts of
the app might never show up when rendered on the server and then hydrated in the browser. The
reason for this is that the server has no access to storage and therefore will always use
initial_value
as described above. So on the server your app is always rendered as if
the value from storage was initial_value
. Then in the browser the actual stored value is used
which might be different, hence during hydration the DOM looks different from the one rendered
on the server which produces the hydration warnings.
The recommended way to avoid this is to use use_cookie
instead because values stored in cookies
are available on the server as well as in the browser.
If you still want to use storage instead of cookies you can use the delay_during_hydration
option that will use the initial_value
during hydration just as on the server and delay loading
the value from storage by an animation frame. This gets rid of the hydration warnings and makes
the app correctly render things. Some flickering might be unavoidable though.
use leptos::*;
use leptos_use::storage::{use_local_storage_with_options, UseStorageOptions};
use codee::string::FromToStringCodec;
#[component]
pub fn Example() -> impl IntoView {
let (flag, set_flag, _) = use_local_storage_with_options::<bool, FromToStringCodec>(
"my-flag",
UseStorageOptions::default().delay_during_hydration(true),
);
view! {
<Show when=move || flag.get()>
<div>Some conditional content</div>
</Show>
}
}
Feature
This function is only available if the crate feature
storage
is enabled
Types
Source
use_active_element
Reactive document.activeElement
Demo
Usage
use leptos::*;
use leptos::logging::log;
use leptos_use::use_active_element;
#[component]
fn Demo() -> impl IntoView {
let active_element = use_active_element();
create_effect(move |_| {
log!("focus changed to {:?}", active_element.get());
});
view! { }
}
Server-Side Rendering
On the server this returns a Signal
that always contains the value None
.
Feature
This function is only available if the crate feature
use_active_element
is enabled
Source
use_document
SSR safe document()
.
This returns just a new-type wrapper around Option<Document>
.
Calling this amounts to None
on the server and Some(Document)
on the client.
It provides some convenient methods for working with the document like body()
.
Usage
use leptos::*;
use leptos_use::use_document;
#[component]
fn Demo() -> impl IntoView {
let document = use_document();
// Returns `None` on the server but will not panic.
let body = document.body();
view! { }
}
Feature
This function is only available if the crate feature
use_document
is enabled
Types
Source
use_document_visibility
Reactively track document.visibilityState
Demo
Usage
use leptos::*;
use leptos_use::use_document_visibility;
#[component]
fn Demo() -> impl IntoView {
let visibility = use_document_visibility();
view! { }
}
Server-Side Rendering
On the server this returns a Signal
that always contains the value web_sys::VisibilityState::Hidden
.
Feature
This function is only available if the crate feature
use_document_visibility
is enabled
Source
use_draggable
Make elements draggable.
Demo
Usage
use leptos::*;
use leptos::html::Div;
use leptos_use::{use_draggable_with_options, UseDraggableOptions, UseDraggableReturn};
use leptos_use::core::Position;
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Div>();
// `style` is a helper string "left: {x}px; top: {y}px;"
let UseDraggableReturn {
x,
y,
style,
..
} = use_draggable_with_options(
el,
UseDraggableOptions::default().initial_value(Position { x: 40.0, y: 40.0 }),
);
view! {
<div node_ref=el style=move || format!("position: fixed; {}", style.get())>
Drag me! I am at { x }, { y }
</div>
}
}
Feature
This function is only available if the crate feature
use_draggable
is enabled
Types
Source
use_drop_zone
Create a zone where files can be dropped.
Demo
Usage
use leptos::*;
use leptos::html::Div;
use leptos_use::{use_drop_zone_with_options, UseDropZoneOptions, UseDropZoneReturn};
#[component]
fn Demo() -> impl IntoView {
let drop_zone_el = create_node_ref::<Div>();
let on_drop = |event| {
// called when files are dropped on zone
};
let UseDropZoneReturn {
is_over_drop_zone,
..
} = use_drop_zone_with_options(
drop_zone_el,
UseDropZoneOptions::default().on_drop(on_drop)
);
view! {
<div node_ref=drop_zone_el>
"Drop files here"
</div>
}
}
Server-Side Rendering
On the server the returned file
signal always contains an empty Vec
and
is_over_drop_zone
contains always false
Feature
This function is only available if the crate feature
use_drop_zone
is enabled
Types
Source
use_element_bounding
Reactive bounding box of an HTML element
Demo
Usage
use leptos::*;
use leptos::html::Div;
use leptos_use::{use_element_bounding, UseElementBoundingReturn};
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Div>();
let UseElementBoundingReturn {
x, y, top,right,bottom,left, width, height, ..
} = use_element_bounding(el);
view! { <div node_ref=el></div> }
}
Server-Side Rendering
On the server the returned signals always are 0.0
and update
is a no-op.
Feature
This function is only available if the crate feature
use_element_bounding
is enabled
Types
Source
use_element_size
Reactive size of an HTML element.
Please refer to ResizeObserver on MDN for more details.
Demo
Usage
use leptos::{html::Div, *};
use leptos_use::{use_element_size, UseElementSizeReturn};
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Div>();
let UseElementSizeReturn { width, height } = use_element_size(el);
view! {
<div node_ref=el>
"Width: " {width}
"Height: " {height}
</div>
}
}
Server-Side Rendering
On the server the returned signals always contain the value of the initial_size
option.
See also
Feature
This function is only available if the crate feature
use_element_size
is enabled
Types
Source
use_element_visibility
Tracks the visibility of an element within the viewport.
Demo
Usage
use leptos::*;
use leptos::html::Div;
use leptos_use::use_element_visibility;
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Div>();
let is_visible = use_element_visibility(el);
view! {
<div node_ref=el>
<h1>{is_visible}</h1>
</div>
}
}
Server-Side Rendering
On the server this returns a Signal
that always contains the value false
.
See also
Feature
This function is only available if the crate feature
use_element_visibility
is enabled
Types
Source
use_intersection_observer
Reactive IntersectionObserver.
Detects that a target element's visibility inside the viewport.
Demo
Usage
use leptos::*;
use leptos::html::Div;
use leptos_use::use_intersection_observer;
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Div>();
let (is_visible, set_visible) = create_signal(false);
use_intersection_observer(
el,
move |entries, _| {
set_visible.set(entries[0].is_intersecting());
},
);
view! {
<div node_ref=el>
<h1>"Hello World"</h1>
</div>
}
}
Server-Side Rendering
On the server this amounts to a no-op.
See also
Feature
This function is only available if the crate feature
use_intersection_observer
is enabled
Types
Source
use_mouse_in_element
Reactive mouse position related to an element.
Demo
Usage
use leptos::*;
use leptos::html::Div;
use leptos_use::{use_mouse_in_element, UseMouseInElementReturn};
#[component]
fn Demo() -> impl IntoView {
let target = create_node_ref::<Div>();
let UseMouseInElementReturn { x, y, is_outside, .. } = use_mouse_in_element(target);
view! {
<div node_ref=target>
<h1>Hello world</h1>
</div>
}
}
Server-Side Rendering
On the server this returns simple Signals with the initial_value
for x
and y
,
no-op for stop
, is_outside = true
and 0.0
for the rest of the signals.
Feature
This function is only available if the crate feature
use_mouse_in_element
is enabled
Types
Source
use_mutation_observer
Reactive MutationObserver.
Watch for changes being made to the DOM tree.
Demo
Usage
use leptos::*;
use leptos::html::Pre;
use leptos_use::{use_mutation_observer_with_options, UseMutationObserverOptions};
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Pre>();
let (text, set_text) = create_signal("".to_string());
use_mutation_observer_with_options(
el,
move |mutations, _| {
if let Some(mutation) = mutations.first() {
set_text.update(|text| *text = format!("{text}\n{:?}", mutation.attribute_name()));
}
},
UseMutationObserverOptions::default().attributes(true),
);
view! {
<pre node_ref=el>{ text }</pre>
}
}
Server-Side Rendering
On the server this amounts to a no-op.
Feature
This function is only available if the crate feature
use_mutation_observer
is enabled
Types
Source
use_resize_observer
Reports changes to the dimensions of an Element's content or the border-box.
Please refer to ResizeObserver on MDN for more details.
Demo
Usage
use leptos::{html::Div, *};
use leptos_use::use_resize_observer;
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Div>();
let (text, set_text) = create_signal("".to_string());
use_resize_observer(
el,
move |entries, observer| {
let rect = entries[0].content_rect();
set_text.set(format!("width: {}\nheight: {}", rect.width(), rect.height()));
},
);
view! {
<div node_ref=el>{ move || text.get() }</div>
}
}
Server-Side Rendering
On the server this amounts to a no-op.
See also
Feature
This function is only available if the crate feature
use_resize_observer
is enabled
Types
Source
use_window
SSR safe window()
.
This returns just a new-type wrapper around Option<Window>
.
Calling this amounts to None
on the server and Some(Window)
on the client.
It provides some convenient methods for working with the window like document()
and navigator()
.
These will all return None
on the server.
Usage
use leptos::*;
use leptos_use::use_window;
#[component]
fn Demo() -> impl IntoView {
let window = use_window();
// Returns `None` on the server but will not panic.
let navigator = window.navigator();
view! { }
}
Feature
This function is only available if the crate feature
use_window
is enabled
Types
Source
use_window_focus
Reactively track window focus
with window.onfocus
and window.onblur
events.
Demo
Usage
use leptos::*;
use leptos_use::use_window_focus;
#[component]
fn Demo() -> impl IntoView {
let focused = use_window_focus();
view! { }
}
Server-Side Rendering
On the server this returns a Signal
that is always true
.
Feature
This function is only available if the crate feature
use_window_focus
is enabled
Source
use_window_scroll
Reactive window scroll.
Demo
Usage
use leptos::*;
use leptos_use::use_window_scroll;
#[component]
fn Demo() -> impl IntoView {
let (x, y) = use_window_scroll();
view! { }
}
Server-Side Rendering
On the server this returns Signal
s that are always 0.0
.
Feature
This function is only available if the crate feature
use_window_scroll
is enabled
Source
use_window_size
Reactive window size.
Demo
Usage
use leptos::*;
use leptos_use::{use_window_size, UseWindowSizeReturn};
#[component]
fn Demo() -> impl IntoView {
let UseWindowSizeReturn { width, height } = use_window_size();
view! { }
}
Server-Side Rendering
On the server the width and height are always initial_size
which defaults to
Size { width: INFINITY, height: INFINITY }
.
Feature
This function is only available if the crate feature
use_window_size
is enabled
Types
Source
use_breakpoints
Reactive viewport breakpoints.
Demo
Usage
use leptos::*;
use leptos_use::{use_breakpoints, BreakpointsTailwind, breakpoints_tailwind};
#[component]
fn Demo() -> impl IntoView {
let screen_width = use_breakpoints(breakpoints_tailwind());
use BreakpointsTailwind::*;
let sm_and_larger = screen_width.ge(Sm);
let larger_than_sm = screen_width.gt(Sm);
let lg_and_smaller = screen_width.le(Lg);
let smaller_than_lg = screen_width.lt(Lg);
view! { }
}
Breakpoints
There are many predefined breakpoints for major UI frameworks. The following are provided.
breakpoints_tailwind
breakpoints_bootstrap_v5
breakpoints_material
breakpoints_ant_design
breakpoints_quasar
breakpoints_semantic
breakpoints_master_css
You can also provide your own breakpoints.
use std::collections::HashMap;
use leptos::*;
use leptos_use::use_breakpoints;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum MyBreakpoints {
Tablet,
Laptop,
Desktop,
}
fn my_breakpoints() -> HashMap<MyBreakpoints, u32> {
use MyBreakpoints::*;
HashMap::from([
(Tablet, 640),
(Laptop, 1024),
(Desktop, 1280),
])
}
#[component]
fn Demo() -> impl IntoView {
let screen_width = use_breakpoints(my_breakpoints());
use MyBreakpoints::*;
let laptop = screen_width.between(Laptop, Desktop);
view! { }
}
Non-reactive methods
For every reactive method there is also a non-reactive variant that is prefixed with is_
use leptos::*;
use leptos_use::{use_breakpoints, BreakpointsTailwind, breakpoints_tailwind};
#[component]
fn Demo() -> impl IntoView {
let screen_width = use_breakpoints(breakpoints_tailwind());
use BreakpointsTailwind::*;
let sm_and_larger = screen_width.is_ge(Sm);
let larger_than_sm = screen_width.is_gt(Sm);
let lg_and_smaller = screen_width.is_le(Lg);
let smaller_than_lg = screen_width.is_lt(Lg);
view! { }
}
Server-Side Rendering
Since internally this uses fn@crate::use_media_query
, which returns always false
on the server,
the returned methods also will return false
.
Feature
This function is only available if the crate feature
use_breakpoints
is enabled
Types
struct UseBreakpointsReturn
enum BreakpointsTailwind
enum BreakpointsBootstrapV5
enum BreakpointsMaterial
enum BreakpointsAntDesign
enum BreakpointsQuasar
enum BreakpointsSemantic
enum BreakpointsMasterCss
Source
use_broadcast_channel
Reactive BroadcastChannel API.
Closes a broadcast channel automatically when the component is cleaned up.
Demo
Usage
The BroadcastChannel interface represents a named channel that any browsing context of a given origin can subscribe to. It allows communication between different documents (in different windows, tabs, frames, or iframes) of the same origin.
Messages are broadcasted via a message event fired at all BroadcastChannel objects listening to the channel.
use leptos::*;
use leptos_use::{use_broadcast_channel, UseBroadcastChannelReturn};
use codee::string::FromToStringCodec;
#[component]
fn Demo() -> impl IntoView {
let UseBroadcastChannelReturn {
is_supported,
message,
post,
error,
close,
..
} = use_broadcast_channel::<bool, FromToStringCodec>("some-channel-name");
post(&true);
close();
view! { }
}
Values are (en)decoded via the given codec. You can use any of the string codecs or a
binary codec wrapped in Base64
.
Please check the codec chapter to see what codecs are available and what feature flags they require.
use leptos::*;
use serde::{Deserialize, Serialize};
use leptos_use::use_broadcast_channel;
use codee::string::JsonSerdeCodec;
// Data sent in JSON must implement Serialize, Deserialize:
#[derive(Serialize, Deserialize, Clone, PartialEq)]
pub struct MyState {
pub playing_lego: bool,
pub everything_is_awesome: String,
}
#[component]
fn Demo() -> impl IntoView {
use_broadcast_channel::<MyState, JsonSerdeCodec>("everyting-is-awesome");
view! { }
}
Feature
This function is only available if the crate feature
use_broadcast_channel
is enabled
Types
Source
use_clipboard
Reactive Clipboard API.
Provides the ability to respond to clipboard commands (cut, copy, and paste) as well as to asynchronously read from and write to the system clipboard. Access to the contents of the clipboard is gated behind the Permissions API. Without user permission, reading or altering the clipboard contents is not permitted.
Demo
Usage
use leptos::*;
use leptos_use::{use_clipboard, UseClipboardReturn};
#[component]
fn Demo() -> impl IntoView {
let UseClipboardReturn { is_supported, text, copied, copy } = use_clipboard();
view! {
<Show
when=move || is_supported.get()
fallback=move || view! { <p>Your browser does not support Clipboard API</p> }
>
<button on:click={
let copy = copy.clone();
move |_| copy("Hello!")
}>
<Show when=move || copied.get() fallback=move || "Copy">
"Copied!"
</Show>
</button>
</Show>
}
}
Server-Side Rendering
On the server the returnd text
signal will always be None
and copy
is a no-op.
Feature
This function is only available if the crate feature
use_clipboard
is enabled
Types
Source
use_color_mode
Reactive color mode (dark / light / customs) with auto data persistence.
Demo
Usage
use leptos::*;
use leptos_use::{use_color_mode, UseColorModeReturn};
#[component]
fn Demo() -> impl IntoView {
let UseColorModeReturn {
mode, // Signal<ColorMode::dark | ColorMode::light>
set_mode,
..
} = use_color_mode();
view! { }
}
By default, it will match with users' browser preference using fn@crate::use_preferred_dark
(a.k.a. ColorMode::Auto
).
When reading the signal, it will by default return the current color mode (ColorMode::Dark
, ColorMode::Light
or
your custom modes ColorMode::Custom("some-custom")
). The ColorMode::Auto
variant can
be included in the returned modes by enabling the emit_auto
option and using use_color_mode_with_options
.
When writing to the signal (set_mode
), it will trigger DOM updates and persist the color mode to local
storage (or your custom storage). You can pass ColorMode::Auto
to set back to auto mode.
use leptos::*;
use leptos_use::{ColorMode, use_color_mode, UseColorModeReturn};
#[component]
fn Demo() -> impl IntoView {
let UseColorModeReturn { mode, set_mode, .. } = use_color_mode();
mode.get(); // ColorMode::Dark or ColorMode::Light
set_mode.set(ColorMode::Dark); // change to dark mode and persist
set_mode.set(ColorMode::Auto); // change to auto mode
view! { }
}
Options
use leptos::*;
use leptos_use::{use_color_mode_with_options, UseColorModeOptions, UseColorModeReturn};
#[component]
fn Demo() -> impl IntoView {
let UseColorModeReturn { mode, set_mode, .. } = use_color_mode_with_options(
UseColorModeOptions::default()
.attribute("theme") // instead of writing to `class`
.custom_modes(vec![
// custom colors in addition to light/dark
"dim".to_string(),
"cafe".to_string(),
]),
); // Signal<ColorMode::Dark | ColorMode::Light | ColorMode::Custom("dim") | ColorMode::Custom("cafe")>
view! { }
}
Cookie
To persist color mode in a cookie, use use_cookie_with_options
and specify .cookie_enabled(true)
.
Note: To work with SSR you have to add the
axum
oractix
feature as described infn@crate::use_cookie
.
use leptos::*;
use leptos_meta::*;
use leptos_use::{use_color_mode_with_options, UseColorModeOptions, UseColorModeReturn};
#[component]
fn Demo() -> impl IntoView {
let UseColorModeReturn { mode, set_mode, .. } = use_color_mode_with_options(
UseColorModeOptions::default()
.cookie_enabled(true),
);
// This adds the color mode class to the `<html>` element even with SSR
view! {
<Html class=move || mode.get().to_string()/>
}
}
For a working example please check out the ssr example.
Server-Side Rendering
On the server this will try to read the
Sec-CH-Prefers-Color-Scheme
header
to determine the color mode. If the header is not present it will return ColorMode::Light
.
Please have a look at the linked documentation above for that header to see browser support
as well as potential server requirements.
If you're using
axum
you have to enable the"axum"
feature in your Cargo.toml. In case it'sactix-web
enable the feature"actix"
, forspin
enable"spin"
.
Bring your own header
In case you're neither using Axum, Actix nor Spin, or the default implementation is not to your liking,
you can provide your own way of reading the color scheme header value using the option
crate::UseColorModeOptions::ssr_color_header_getter
.
Cookie
If cookie_enabled
is set to true
, a cookie will be used and if present this value will be used
on the server as well as on the client. Please note that you have to add the axum
or actix
feature as described in fn@crate::use_cookie
.
See also
Feature
This function is only available if the crate feature
use_color_mode
is enabled
Types
Source
use_cookie
SSR-friendly and reactive cookie access.
You can use this function multiple times for the same cookie and their signals will synchronize
(even across windows/tabs). But there is no way to listen to changes to document.cookie
directly so in case
something outside of this function changes the cookie, the signal will not be updated.
When the options max_age
or expire
is given then the returned signal will
automatically turn to None
after that time.
Demo
Usage
The example below creates a cookie called counter
. If the cookie doesn't exist, it is initially set to a random value.
Whenever we update the counter
variable, the cookie will be updated accordingly.
use leptos::*;
use leptos_use::use_cookie;
use codee::string::FromToStringCodec;
use rand::prelude::*;
#[component]
fn Demo() -> impl IntoView {
let (counter, set_counter) = use_cookie::<u32, FromToStringCodec>("counter");
let reset = move || set_counter.set(Some(random()));
if counter.get().is_none() {
reset();
}
let increase = move || {
set_counter.set(counter.get().map(|c| c + 1));
};
view! {
<p>Counter: {move || counter.get().map(|c| c.to_string()).unwrap_or("β".to_string())}</p>
<button on:click=move |_| reset()>Reset</button>
<button on:click=move |_| increase()>+</button>
}
}
Values are (en)decoded via the given codec. You can use any of the string codecs or a
binary codec wrapped in Base64
.
Please check the codec chapter to see what codecs are available and what feature flags they require.
Cookie attributes
As part of the options when you use use_cookie_with_options
you can specify cookie attributes.
use cookie::SameSite;
use leptos::*;
use leptos_use::{use_cookie_with_options, UseCookieOptions};
use codee::string::FromToStringCodec;
#[component]
fn Demo() -> impl IntoView {
let (cookie, set_cookie) = use_cookie_with_options::<bool, FromToStringCodec>(
"user_info",
UseCookieOptions::default()
.max_age(3600_000) // one hour
.same_site(SameSite::Lax)
);
view! {}
}
Server-Side Rendering
This works equally well on the server or the client.
On the server this function reads the cookie from the HTTP request header and writes it back into
the HTTP response header according to options (if provided).
The returned WriteSignal
may not affect the cookie headers on the server! It will try and write
the headers buy if this happens after the headers have already been streamed to the client then
this will have no effect.
If you're using
axum
you have to enable the"axum"
feature in your Cargo.toml. In case it'sactix-web
enable the feature"actix"
, forspin
enable"spin"
.
Bring your own header
In case you're neither using Axum, Actix nor Spin, or the default implementation is not to your liking, you can provide your own way of reading and writing the cookie header value.
use cookie::Cookie;
use leptos::*;
use serde::{Deserialize, Serialize};
use leptos_use::{use_cookie_with_options, UseCookieOptions};
use codee::string::JsonSerdeCodec;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct Auth {
pub username: String,
pub token: String,
}
#[component]
fn Demo() -> impl IntoView {
use_cookie_with_options::<Auth, JsonSerdeCodec>(
"auth",
UseCookieOptions::default()
.ssr_cookies_header_getter(|| {
#[cfg(feature = "ssr")]
{
Some("Somehow get the value of the cookie header as a string".to_owned())
}
})
.ssr_set_cookie(|cookie: &Cookie| {
#[cfg(feature = "ssr")]
{
// somehow insert the Set-Cookie header for this cookie
}
}),
);
view! {}
}
Feature
This function is only available if the crate feature
use_cookie
is enabled
Types
Source
use_css_var
Manipulate CSS variables.
Demo
Usage
use leptos::*;
use leptos_use::use_css_var;
#[component]
fn Demo() -> impl IntoView {
let (color, set_color) = use_css_var("--color");
set_color.set("red".to_string());
view! { }
}
The variable name itself can be a Signal
.
use leptos::*;
use leptos_use::use_css_var;
#[component]
fn Demo() -> impl IntoView {
let (key, set_key) = create_signal("--color".to_string());
let (color, set_color) = use_css_var(key);
view! { }
}
You can specify the element that the variable is applied to as well as an initial value in case the variable is not set yet. The option to listen for changes to the variable is also available.
use leptos::*;
use leptos::html::Div;
use leptos_use::{use_css_var_with_options, UseCssVarOptions};
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Div>();
let (color, set_color) = use_css_var_with_options(
"--color",
UseCssVarOptions::default()
.target(el)
.initial_value("#eee")
.observe(true),
);
view! {
<div node_ref=el>"..."</div>
}
}
Server-Side Rendering
On the server this simply returns create_signal(options.initial_value)
.
Feature
This function is only available if the crate feature
use_css_var
is enabled
Types
Source
use_display_media
Reactive mediaDevices.getDisplayMedia
streaming.
Demo
Usage
use leptos::*;
use leptos_use::{use_display_media, UseDisplayMediaReturn};
#[component]
fn Demo() -> impl IntoView {
let video_ref = create_node_ref::<leptos::html::Video>();
let UseDisplayMediaReturn { stream, start, .. } = use_display_media();
start();
create_effect(move |_|
video_ref.get().map(|v| {
match stream.get() {
Some(Ok(s)) => v.set_src_object(Some(&s)),
Some(Err(e)) => logging::error!("Failed to get media stream: {:?}", e),
None => logging::log!("No stream yet"),
}
})
);
view! { <video node_ref=video_ref controls=false autoplay=true muted=true></video> }
}
Server-Side Rendering
On the server calls to start
or any other way to enable the stream will be ignored
and the stream will always be None
.
Feature
This function is only available if the crate feature
use_display_media
is enabled
Types
Source
use_event_listener
Use EventListener with ease.
Register using addEventListener on mounted, and removeEventListener automatically on cleanup.
Usage
use leptos::*;
use leptos::ev::visibilitychange;
use leptos::logging::log;
use leptos_use::{use_document, use_event_listener};
#[component]
fn Demo() -> impl IntoView {
use_event_listener(use_document(), visibilitychange, |evt| {
log!("{:?}", evt);
});
view! { }
}
You can also pass a NodeRef
as the event target, use_event_listener
will unregister the previous event and register
the new one when you change the target.
use leptos::*;
use leptos::ev::click;
use leptos::logging::log;
use leptos_use::use_event_listener;
#[component]
fn Demo() -> impl IntoView {
let element = create_node_ref();
use_event_listener(element, click, |evt| {
log!("click from element {:?}", event_target::<web_sys::HtmlDivElement>(&evt));
});
let (cond, set_cond) = create_signal(true);
view! {
<Show
when=move || cond.get()
fallback=move || view! { <div node_ref=element>"Condition false"</div> }
>
<div node_ref=element>"Condition true"</div>
</Show>
}
}
You can also call the returned to unregister the listener.
use leptos::*;
use leptos::ev::keydown;
use leptos::logging::log;
use web_sys::KeyboardEvent;
use leptos_use::use_event_listener;
#[component]
fn Demo() -> impl IntoView {
let cleanup = use_event_listener(document().body(), keydown, |evt: KeyboardEvent| {
log!("{}", &evt.key());
});
cleanup();
view! { }
}
Server-Side Rendering
On the server this amounts to a noop.
Feature
This function is only available if the crate feature
use_event_listener
is enabled
Types
Source
use_favicon
Reactive favicon.
Demo
Usage
use leptos::*;
use leptos_use::use_favicon;
#[component]
fn Demo() -> impl IntoView {
let (icon, set_icon) = use_favicon();
set_icon.set(Some("dark.png".to_string())); // change current icon
view! { }
}
Passing a Source Signal
You can pass a Signal
to use_favicon_with_options
. Change from the source signal will be
reflected in your favicon automatically.
use leptos::*;
use leptos_use::{use_favicon_with_options, UseFaviconOptions, use_preferred_dark};
#[component]
fn Demo() -> impl IntoView {
let is_dark = use_preferred_dark();
let (icon, _) = use_favicon_with_options(
UseFaviconOptions::default().new_icon(
Signal::derive(move || {
Some((if is_dark.get() { "dark.png" } else { "light.png" }).to_string())
}),
)
);
view! { }
}
Server-Side Rendering
On the server only the signals work but no favicon will be changed obviously.
Feature
This function is only available if the crate feature
use_favicon
is enabled
Types
Source
use_media_query
Reactive Media Query.
Demo
Usage
use leptos::*;
use leptos_use::use_media_query;
#[component]
fn Demo() -> impl IntoView {
let is_large_screen = use_media_query("(min-width: 1024px)");
let is_dark_preferred = use_media_query("(prefers-color-scheme: dark)");
view! { }
}
Server-Side Rendering
On the server this functions returns a Signal that is always false
.
See also
Feature
This function is only available if the crate feature
use_media_query
is enabled
Source
use_permission
Reactive Permissions API.
Demo
Usage
use leptos::*;
use leptos_use::use_permission;
#[component]
fn Demo() -> impl IntoView {
let microphone_access = use_permission("microphone");
view! { }
}
Server-Side Rendering
On the server the returned signal will always be PermissionState::Unknown
.
Feature
This function is only available if the crate feature
use_permission
is enabled
Types
Source
use_preferred_contrast
Reactive prefers-contrast media query.
Usage
use leptos::*;
use leptos_use::use_preferred_contrast;
#[component]
fn Demo() -> impl IntoView {
let preferred_contrast = use_preferred_contrast();
view! { }
}
Server-Side Rendering
On the server this returns a Signal
that always contains the value PreferredContrast::NoPreference
.
See also
Feature
This function is only available if the crate feature
use_preferred_contrast
is enabled
Types
Source
use_preferred_dark
Reactive dark theme preference.
Usage
use leptos::*;
use leptos_use::use_preferred_dark;
#[component]
fn Demo() -> impl IntoView {
let is_dark_preferred = use_preferred_dark();
view! { }
}
Server-Side Rendering
On the server this will try to read the
Sec-CH-Prefers-Color-Scheme
header
to determine the color mode. If the header is not present it will return ColorMode::Light
.
Please have a look at the linked documentation above for that header to see browser support
as well as potential server requirements.
If you're using
axum
you have to enable the"axum"
feature in your Cargo.toml. In case it'sactix-web
enable the feature"actix"
, forspin
enable"spin"
.
Bring your own header
In case you're neither using Axum, Actix nor Spin, or the default implementation is not to your liking,
you can provide your own way of reading the color scheme header value using the option
crate::UsePreferredDarkOptions::ssr_color_header_getter
.
See also
Feature
This function is only available if the crate feature
use_preferred_dark
is enabled
Types
Source
use_prefers_reduced_motion
Reactive reduced motions preference.
Demo
Usage
use leptos::*;
use leptos_use::use_prefers_reduced_motion;
use leptos_use::docs::BooleanDisplay;
#[component]
fn Demo() -> impl IntoView {
let is_reduced_motion_preferred = use_prefers_reduced_motion();
view! {
<div>
<p>Prefers reduced motions: <BooleanDisplay value=is_reduced_motion_preferred/></p>
<p>
Update reduce motion preference
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion#user_preferences">
documentation.
</a>
</p>
</div>
}
}
Server-Side Rendering
On the server this will try to read the
Sec-CH-Prefers-Reduced-Motion
header
to indicate the preference for animations to be displayed with reduced motion.
Please have a look at the linked documentation above to see browser support
as well as potential serve requirements.
If you're using
axum
you have to enable the"axum"
feature in your Cargo.toml. In case it'sactix-web
enable the feature"actix"
, forspin
enable"spin"
.
Bring your own header
In case you're neither using Axum, Actix nor Spin, or the default implementation is not to your
liking, you can provide your own way of reading the reduced motion header value using the option
crate::UsePrefersReducedMotionOptions::ssr_motion_header_getter
.
See also
Feature
This function is only available if the crate feature
use_prefers_reduced_motion
is enabled
Types
Source
use_service_worker
Reactive ServiceWorker API.
Please check the working example.
Usage
use leptos::*;
use leptos_use::{use_service_worker_with_options, UseServiceWorkerOptions, UseServiceWorkerReturn};
#[component]
fn Demo() -> impl IntoView {
let UseServiceWorkerReturn {
registration,
installing,
waiting,
active,
skip_waiting,
check_for_update,
} = use_service_worker_with_options(UseServiceWorkerOptions::default()
.script_url("service-worker.js")
.skip_waiting_message("skipWaiting"),
);
view! { }
}
Server-Side Rendering
This function does not support SSR. Call it inside a create_effect
.
Feature
This function is only available if the crate feature
use_service_worker
is enabled
Types
Source
use_textarea_autosize
Automatically update the height of a textarea depending on the content.
Demo
Usage
Simple example
use leptos::*;
use leptos::html::Textarea;
use leptos_use::{use_textarea_autosize, UseTextareaAutosizeReturn};
#[component]
fn Demo() -> impl IntoView {
let textarea = create_node_ref::<Textarea>();
let UseTextareaAutosizeReturn {
content,
set_content,
trigger_resize
} = use_textarea_autosize(textarea);
view! {
<textarea
value=content
on:input=move |evt| set_content.set(event_target_value(&evt))
node_ref=textarea
class="resize-none"
placeholder="What's on your mind?"
/>
}
}
Make sure that you set
box-sizing: border-box
on the textarea element.It's also recommended to reset the scrollbar styles for the textarea element to avoid incorrect height values for large amounts of text.
textarea {
-ms-overflow-style: none;
scrollbar-width: none;
}
textarea::-webkit-scrollbar {
display: none;
}
With rows
attribute
If you need support for the rows attribute on a textarea element, then you should set the
style_prop
option to "min-height"
.
use leptos::*;
use leptos::html::Textarea;
use leptos_use::{use_textarea_autosize_with_options, UseTextareaAutosizeOptions, UseTextareaAutosizeReturn};
#[component]
fn Demo() -> impl IntoView {
let textarea = create_node_ref::<Textarea>();
let UseTextareaAutosizeReturn {
content,
set_content,
..
} = use_textarea_autosize_with_options(
textarea,
UseTextareaAutosizeOptions::default().style_prop("min-height"),
);
view! {
<textarea
value=content
on:input=move |evt| set_content.set(event_target_value(&evt))
node_ref=textarea
class="resize-none"
placeholder="What's on your mind?"
rows="3"
/>
}
}
Server-Side Rendering
On the server this will always return an empty string as Β΄contentand a no-op
trigger_resize`.
Feature
This function is only available if the crate feature
use_textarea_autosize
is enabled
Types
Source
use_user_media
Reactive mediaDevices.getUserMedia
streaming.
Demo
Usage
use leptos::*;
use leptos_use::{use_user_media, UseUserMediaReturn};
#[component]
fn Demo() -> impl IntoView {
let video_ref = create_node_ref::<leptos::html::Video>();
let UseUserMediaReturn { stream, start, .. } = use_user_media();
start();
create_effect(move |_|
video_ref.get().map(|v| {
match stream.get() {
Some(Ok(s)) => v.set_src_object(Some(&s)),
Some(Err(e)) => logging::error!("Failed to get media stream: {:?}", e),
None => logging::log!("No stream yet"),
}
})
);
view! { <video node_ref=video_ref controls=false autoplay=true muted=true></video> }
}
Server-Side Rendering
On the server calls to start
or any other way to enable the stream will be ignored
and the stream will always be None
.
Feature
This function is only available if the crate feature
use_user_media
is enabled
Types
struct UseUserMediaOptions
struct UseUserMediaReturn
enum ConstraintExactIdeal
enum ConstraintRange
enum FacingMode
enum AudioConstraints
enum VideoConstraints
struct VecMarker
struct AudioTrackConstraints
struct VideoTrackConstraints
Source
use_web_lock
Rustified Web Locks API.
The Web Locks API allows scripts running in one tab or worker to asynchronously acquire a lock, hold it while work is performed, then release it. While held, no other script executing in the same origin can acquire the same lock, which allows a web app running in multiple tabs or workers to coordinate work and the use of resources.
This function requires
--cfg=web_sys_unstable_apis
to be activated as described in the wasm-bindgen guide.
Demo
Usage
use leptos::*;
use leptos_use::use_web_lock;
async fn my_process(_lock: web_sys::Lock) -> i32 {
// do sth
42
}
#[component]
fn Demo() -> impl IntoView {
spawn_local(async {
let res = use_web_lock("my_lock", my_process).await;
assert!(matches!(res, Ok(42)));
});
view! { }
}
Server-Side Rendering
On the server this returns Err(UseWebLockError::Server)
and the task is not executed.
Feature
This function is only available if the crate feature
use_web_lock
is enabled
Types
Source
use_web_notification
Reactive Notification API.
The Web Notification interface of the Notifications API is used to configure and display desktop notifications to the user.
Demo
Usage
use leptos::*;
use leptos_use::{use_web_notification_with_options, UseWebNotificationOptions, ShowOptions, UseWebNotificationReturn, NotificationDirection};
#[component]
fn Demo() -> impl IntoView {
let UseWebNotificationReturn {
show,
close,
..
} = use_web_notification_with_options(
UseWebNotificationOptions::default()
.direction(NotificationDirection::Auto)
.language("en")
.renotify(true)
.tag("test"),
);
show(ShowOptions::default().title("Hello World from leptos-use"));
view! { }
}
Server-Side Rendering
This function is basically ignored on the server. You can safely call show
but it will do nothing.
Feature
This function is only available if the crate feature
use_web_notification
is enabled
Types
enum NotificationDirection
struct UseWebNotificationOptions
struct ShowOptions
enum NotificationPermission
struct UseWebNotificationReturn
Source
on_click_outside
Listen for clicks outside of an element. Useful for modals or dropdowns.
Demo
Usage
use leptos::*;
use leptos::logging::log;
use leptos::html::Div;
use leptos_use::on_click_outside;
#[component]
fn Demo() -> impl IntoView {
let target = create_node_ref::<Div>();
on_click_outside(target, move |event| { log!("{:?}", event); });
view! {
<div node_ref=target>"Hello World"</div>
<div>"Outside element"</div>
}
}
This function uses Event.composedPath() which is not supported by IE 11, Edge 18 and below. If you are targeting these browsers, we recommend you to include this code snippet on your project.
Excluding Elements
Use this to ignore clicks on certain elements.
use leptos::*;
use leptos::logging::log;
use leptos::html::Div;
use leptos_use::{on_click_outside_with_options, OnClickOutsideOptions};
#[component]
fn Demo() -> impl IntoView {
let target = create_node_ref::<Div>();
on_click_outside_with_options(
target,
move |event| { log!("{:?}", event); },
OnClickOutsideOptions::default().ignore(["input", "#some-id"]),
);
view! {
<div node_ref=target>"Hello World"</div>
}
}
Server-Side Rendering
On the server this amounts to a no-op.
Feature
This function is only available if the crate feature
on_click_outside
is enabled
Types
Source
use_device_orientation
Reactive DeviceOrientationEvent.
Provide web developers with information from the physical orientation of the device running the web page.
Demo
Usage
use leptos::*;
use leptos_use::{use_device_orientation, UseDeviceOrientationReturn};
#[component]
fn Demo() -> impl IntoView {
let UseDeviceOrientationReturn {
is_supported,
absolute,
alpha,
beta,
gamma,
} = use_device_orientation();
view! { }
}
Server-Side Rendering
On the server this function returns values as if the orientation capabilties were not supported by the device.
Feature
This function is only available if the crate feature
use_device_orientation
is enabled
Types
Source
use_device_pixel_ratio
Reactive window.devicePixelRatio
NOTE: there is no event listener for
window.devicePixelRatio
change. So this function uses the same mechanism as described in this example.
Demo
Usage
use leptos::*;
use leptos_use::use_device_pixel_ratio;
#[component]
fn Demo() -> impl IntoView {
let pixel_ratio = use_device_pixel_ratio();
view! { }
}
Server-Side Rendering
On the server this function returns a Signal that is always 1.0
.
Feature
This function is only available if the crate feature
use_device_pixel_ratio
is enabled
Source
use_element_hover
Reactive element's hover state.
Demo
Usage
use leptos::*;
use leptos::html::Button;
use leptos_use::use_element_hover;
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Button>();
let is_hovered = use_element_hover(el);
view! {
<button node_ref=el>{ move || format!("{:?}", is_hovered.get()) }</button>
}
}
Server-Side Rendering
On the server this returns a Signal
that always contains the value false
.
Feature
This function is only available if the crate feature
use_element_hover
is enabled
Types
Source
use_geolocation
Reactive Geolocation API.
It allows the user to provide their location to web applications if they so desire. For privacy reasons, the user is asked for permission to report location information.
Demo
Usage
use leptos::*;
use leptos_use::{use_geolocation, UseGeolocationReturn};
#[component]
fn Demo() -> impl IntoView {
let UseGeolocationReturn {
coords,
located_at,
error,
resume,
pause,
} = use_geolocation();
view! { }
}
Server-Side Rendering
On the server all signals returns will always contain None
and the functions do nothing.
Feature
This function is only available if the crate feature
use_geolocation
is enabled
Types
Source
use_idle
Demo
Usage
use leptos::*;
use leptos::logging::log;
use leptos_use::{use_idle, UseIdleReturn};
#[component]
fn Demo() -> impl IntoView {
let UseIdleReturn {
idle, last_active, ..
} = use_idle(5 * 60 * 1000); // 5 minutes
log!("{}", idle.get()); // true or false
view! { }
}
Programatically resetting:
use std::time::Duration;
use leptos::*;
use leptos::logging::log;
use leptos_use::{use_idle, UseIdleReturn};
#[component]
fn Demo() -> impl IntoView {
let UseIdleReturn {
idle, last_active, reset
} = use_idle(5 * 60 * 1000); // 5 minutes
reset(); // restarts the idle timer. Does not change the `last_active` value.
view! { }
}
Server-Side Rendering
On the server this will always return static signals
UseIdleReturn{
idle: Signal(initial_state),
last_active: Signal(now),
reset: || {}
}
Feature
This function is only available if the crate feature
use_idle
is enabled
Types
Source
use_infinite_scroll
Infinite scrolling of the element.
Demo
Usage
use leptos::*;
use leptos::html::Div;
use leptos_use::{use_infinite_scroll_with_options, UseInfiniteScrollOptions};
#[component]
fn Demo() -> impl IntoView {
let el = create_node_ref::<Div>();
let (data, set_data) = create_signal(vec![1, 2, 3, 4, 5, 6]);
let _ = use_infinite_scroll_with_options(
el,
move |_| async move {
let len = data.with(|d| d.len());
set_data.update(|data| *data = (1..len+6).collect());
},
UseInfiniteScrollOptions::default().distance(10.0),
);
view! {
<div node_ref=el>
<For each=move || data.get() key=|i| *i let:item>{ item }</For>
</div>
}
}
The returned signal is true
while new data is being loaded.
Feature
This function is only available if the crate feature
use_infinite_scroll
is enabled
Types
Source
use_mouse
Reactive mouse position
Demo
Basic Usage
use leptos::*;
use leptos_use::{use_mouse, UseMouseReturn};
#[component]
fn Demo() -> impl IntoView {
let UseMouseReturn {
x, y, source_type, ..
} = use_mouse();
view! { }
}
Touch is enabled by default. To only detect mouse changes, set touch
to false
.
The dragover
event is used to track mouse position while dragging.
use leptos::*;
use leptos_use::{use_mouse_with_options, UseMouseOptions, UseMouseReturn};
#[component]
fn Demo() -> impl IntoView {
let UseMouseReturn {
x, y, ..
} = use_mouse_with_options(
UseMouseOptions::default().touch(false)
);
view! { }
}
Custom Extractor
It's also possible to provide a custom extractor to get the position from the events.
use leptos::*;
use leptos::html::Div;
use web_sys::MouseEvent;
use leptos_use::{use_mouse_with_options, UseMouseOptions, UseMouseReturn, UseMouseEventExtractor, UseMouseCoordType};
#[derive(Clone)]
struct MyExtractor;
impl UseMouseEventExtractor for MyExtractor {
fn extract_mouse_coords(&self, event: &MouseEvent) -> Option<(f64, f64)> {
Some((event.offset_x() as f64, event.offset_y() as f64))
}
// don't implement fn extract_touch_coords to ignore touch events
}
#[component]
fn Demo() -> impl IntoView {
let element = create_node_ref::<Div>();
let UseMouseReturn {
x, y, source_type, ..
} = use_mouse_with_options(
UseMouseOptions::default()
.target(element)
.coord_type(UseMouseCoordType::Custom(MyExtractor))
);
view! { <div node_ref=element></div> }
}
Server-Side Rendering
On the server this returns simple Signal
s with the initial_value
s.
Feature
This function is only available if the crate feature
use_mouse
is enabled
Types
Source
use_scroll
We have to check if the scroll amount is close enough to some threshold in order to more accurately calculate arrivedState. This is because scrollTop/scrollLeft are non-rounded numbers, while scrollHeight/scrollWidth and clientHeight/clientWidth are rounded. https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#determine_if_an_element_has_been_totally_scrolled
Feature
This function is only available if the crate feature
use_scroll
is enabled
Types
Source
use_event_source
Reactive EventSource
An EventSource or Server-Sent-Events instance opens a persistent connection to an HTTP server, which sends events in text/event-stream format.
Usage
Values are decoded via the given decoder. You can use any of the string codecs or a
binary codec wrapped in Base64
.
Please check the codec chapter to see what codecs are available and what feature flags they require.
use leptos::*;
use leptos_use::{use_event_source, UseEventSourceReturn};
use codee::string::JsonSerdeCodec;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, PartialEq)]
pub struct EventSourceData {
pub message: String,
pub priority: u8,
}
#[component]
fn Demo() -> impl IntoView {
let UseEventSourceReturn {
ready_state, data, error, close, ..
} = use_event_source::<EventSourceData, JsonSerdeCodec>("https://event-source-url");
view! { }
}
Named Events
You can define named events when using use_event_source_with_options
.
use leptos::*;
use leptos_use::{use_event_source_with_options, UseEventSourceReturn, UseEventSourceOptions};
use codee::string::FromToStringCodec;
#[component]
fn Demo() -> impl IntoView {
let UseEventSourceReturn {
ready_state, data, error, close, ..
} = use_event_source_with_options::<String, FromToStringCodec>(
"https://event-source-url",
UseEventSourceOptions::default()
.named_events(["notice".to_string(), "update".to_string()])
);
view! { }
}
Immediate
Auto-connect (enabled by default).
This will call open()
automatically for you, and you don't need to call it by yourself.
Auto-Reconnection
Reconnect on errors automatically (enabled by default).
You can control the number of reconnection attempts by setting reconnect_limit
and the
interval between them by setting reconnect_interval
.
use leptos::*;
use leptos_use::{use_event_source_with_options, UseEventSourceReturn, UseEventSourceOptions, ReconnectLimit};
use codee::string::FromToStringCodec;
#[component]
fn Demo() -> impl IntoView {
let UseEventSourceReturn {
ready_state, data, error, close, ..
} = use_event_source_with_options::<bool, FromToStringCodec>(
"https://event-source-url",
UseEventSourceOptions::default()
.reconnect_limit(ReconnectLimit::Limited(5)) // at most 5 attempts
.reconnect_interval(2000) // wait for 2 seconds between attempts
);
view! { }
}
To disable auto-reconnection, set reconnect_limit
to 0
.
Server-Side Rendering
On the server-side, use_event_source
will always return ready_state
as ConnectionReadyState::Closed
,
data
, event
and error
will always be None
, and open
and close
will do nothing.
Feature
This function is only available if the crate feature
use_event_source
is enabled
Types
Source
use_websocket
Creating and managing a Websocket connection.
Demo
Usage
Values are (en)decoded via the given codec. You can use any of the codecs, string or binary.
Please check the codec chapter to see what codecs are available and what feature flags they require.
use leptos::*;
use codee::string::FromToStringCodec;
use leptos_use::{use_websocket, UseWebSocketReturn};
use leptos_use::core::ConnectionReadyState;
#[component]
fn Demo() -> impl IntoView {
let UseWebSocketReturn {
ready_state,
message,
send,
open,
close,
..
} = use_websocket::<String, String, FromToStringCodec>("wss://echo.websocket.events/");
let send_message = move |_| {
send(&"Hello, world!".to_string());
};
let status = move || ready_state.get().to_string();
let connected = move || ready_state.get() == ConnectionReadyState::Open;
let open_connection = move |_| {
open();
};
let close_connection = move |_| {
close();
};
view! {
<div>
<p>"status: " {status}</p>
<button on:click=send_message disabled=move || !connected()>"Send"</button>
<button on:click=open_connection disabled=connected>"Open"</button>
<button on:click=close_connection disabled=move || !connected()>"Close"</button>
<p>"Receive message: " {move || format!("{:?}", message.get())}</p>
</div>
}
}
Here is another example using msgpack
for encoding and decoding. This means that only binary
messages can be sent or received. For this to work you have to enable the msgpack_serde
feature flag.
use leptos::*;
use codee::binary::MsgpackSerdeCodec;
use leptos_use::{use_websocket, UseWebSocketReturn};
use serde::{Deserialize, Serialize};
#[component]
fn Demo() -> impl IntoView {
#[derive(Serialize, Deserialize)]
struct SomeData {
name: String,
count: i32,
}
let UseWebSocketReturn {
message,
send,
..
} = use_websocket::<SomeData, SomeData, MsgpackSerdeCodec>("wss://some.websocket.server/");
let send_data = move || {
send(&SomeData {
name: "John Doe".to_string(),
count: 42,
});
};
view! {}
}
Relative Paths
If the provided url
is relative, it will be resolved relative to the current page.
Urls will be resolved like this the following. Please note that the protocol (http vs https) will
be taken into account as well.
Current Page | Relative Url | Resolved Url |
---|---|---|
http://example.com/some/where | /api/ws | ws://example.com/api/ws |
https://example.com/some/where | /api/ws | wss://example.com/api/ws |
https://example.com/some/where | api/ws | wss://example.com/some/where/api/ws |
https://example.com/some/where | //otherdomain.com/api/ws | wss://otherdomain.com/api/ws |
Usage with provide_context
The return value of use_websocket
utilizes several type parameters which can make it
cumbersome to use with provide_context
+ expect_context
.
The following example shows how to avoid type parameters with dynamic dispatch.
This sacrifices a little bit of performance for the sake of ergonomics. However,
compared to network transmission speeds this loss of performance is negligible.
First we define the struct
that is going to be passed around as context.
use leptos::*;
use std::rc::Rc;
#[derive(Clone)]
pub struct WebsocketContext {
pub message: Signal<Option<String>>,
send: Rc<dyn Fn(&String)>, // use Rc to make it easily cloneable
}
impl WebsocketContext {
pub fn new(message: Signal<Option<String>>, send: Rc<dyn Fn(&String)>) -> Self {
Self {
message,
send,
}
}
// create a method to avoid having to use parantheses around the field
#[inline(always)]
pub fn send(&self, message: &str) {
(self.send)(&message.to_string())
}
}
Now you can provide the context like the following.
use leptos::*;
use codee::string::FromToStringCodec;
use leptos_use::{use_websocket, UseWebSocketReturn};
use std::rc::Rc;
#[derive(Clone)]
pub struct WebsocketContext {
pub message: Signal<Option<String>>,
send: Rc<dyn Fn(&String)>,
}
impl WebsocketContext {
pub fn new(message: Signal<Option<String>>, send: Rc<dyn Fn(&String)>) -> Self {
Self {
message,
send,
}
}
}
#[component]
fn Demo() -> impl IntoView {
let UseWebSocketReturn {
message,
send,
..
} = use_websocket::<String, String, FromToStringCodec>("ws:://some.websocket.io");
provide_context(WebsocketContext::new(message, Rc::new(send.clone())));
view! {}
}
Finally let's use the context:
use leptos::*;
use leptos_use::{use_websocket, UseWebSocketReturn};
use std::rc::Rc;
#[derive(Clone)]
pub struct WebsocketContext {
pub message: Signal<Option<String>>,
send: Rc<dyn Fn(&String)>,
}
impl WebsocketContext {
#[inline(always)]
pub fn send(&self, message: &str) {
(self.send)(&message.to_string())
}
}
#[component]
fn Demo() -> impl IntoView {
let websocket = expect_context::<WebsocketContext>();
websocket.send("Hello World!");
view! {}
}
Server-Side Rendering
On the server the returned functions amount to no-ops.
Feature
This function is only available if the crate feature
use_websocket
is enabled
Types
Source
use_interval
Reactive counter increases on every interval.
Demo
Usage
use leptos::*;
use leptos_use::{use_interval, UseIntervalReturn};
#[component]
fn Demo() -> impl IntoView {
let UseIntervalReturn {
counter,
reset,
is_active,
pause,
resume
} = use_interval( 200 );
view! { }
}
Server-Side Rendering
On the server this function will simply be ignored.
Feature
This function is only available if the crate feature
use_interval
is enabled
Types
Source
use_interval_fn
Wrapper for set_interval
with controls.
Demo
Usage
use leptos::*;
use leptos_use::use_interval_fn;
use leptos_use::utils::Pausable;
#[component]
fn Demo() -> impl IntoView {
let Pausable { pause, resume, is_active } = use_interval_fn(
|| {
// do something
},
1000,
);
view! { }
}
Server-Side Rendering
On the server this function will simply be ignored.
Feature
This function is only available if the crate feature
use_interval_fn
is enabled
Types
Source
use_raf_fn
Call function on every requestAnimationFrame. With controls of pausing and resuming.
Demo
Usage
use leptos::*;
use leptos_use::use_raf_fn;
use leptos_use::utils::Pausable;
#[component]
fn Demo() -> impl IntoView {
let (count, set_count) = create_signal(0);
let Pausable { pause, resume, is_active } = use_raf_fn(move |_| {
set_count.update(|count| *count += 1);
});
view! { <div>Count: { count }</div> }
}
You can use use_raf_fn_with_options
and set immediate
to false
. In that case
you have to call resume()
before the callback
is executed.
Server-Side Rendering
On the server this does basically nothing. The provided closure will never be called.
Feature
This function is only available if the crate feature
use_raf_fn
is enabled
Types
Source
use_timeout_fn
Wrapper for setTimeout
with controls.
Demo
Usage
use leptos::*;
use leptos_use::{use_timeout_fn, UseTimeoutFnReturn};
#[component]
fn Demo() -> impl IntoView {
let UseTimeoutFnReturn { start, stop, is_pending, .. } = use_timeout_fn(
|i: i32| {
// do sth
},
3000.0
);
start(3);
view! { }
}
Server-Side Rendering
On the server the callback will never be run. The returned functions are all no-ops and
is_pending
will always be false
.
Feature
This function is only available if the crate feature
use_timeout_fn
is enabled
Types
Source
use_timestamp
Reactive current timestamp.
Demo
Usage
use leptos::*;
use leptos_use::use_timestamp;
#[component]
fn Demo() -> impl IntoView {
let timestamp = use_timestamp();
view! { }
}
With controls:
use leptos::*;
use leptos_use::{use_timestamp_with_controls, UseTimestampReturn};
#[component]
fn Demo() -> impl IntoView {
let UseTimestampReturn {
timestamp,
is_active,
pause,
resume,
} = use_timestamp_with_controls();
view! { }
}
Server-Side Rendering
On the server this function will return a signal with the milliseconds since the Unix epoch.
But the signal will never update (as there's no request_animation_frame
on the server).
Feature
This function is only available if the crate feature
use_timestamp
is enabled
Types
Source
watch_debounced
A debounced version of watch
.
Demo
Usage
use leptos::*;
use leptos::logging::log;
use leptos_use::watch_debounced;
pub fn Demo() -> impl IntoView {
let (source, set_source) = create_signal(0);
watch_debounced(
move || source.get(),
move |_, _, _| {
log!("changed!");
},
500.0,
);
view! { }
}
This really is only shorthand shorthand for watch_with_options(deps, callback, WatchOptions::default().debounce(ms))
.
Please note that if the current component is cleaned up before the debounced callback is called, the debounced callback will not be called.
There's also watch_debounced_with_options
where you can specify the other watch options (except filter
).
use leptos::*;
use leptos::logging::log;
use leptos_use::{watch_debounced_with_options, WatchDebouncedOptions};
pub fn Demo() -> impl IntoView {
let (source, set_source) = create_signal(0);
watch_debounced_with_options(
move || source.get(),
move |_, _, _| {
log!("changed!");
},
500.0,
WatchDebouncedOptions::default().max_wait(Some(1000.0)),
);
view! { }
}
Recommended Reading
Server-Side Rendering
On the server the callback
will never be called except if you set immediate
to true
in which case the callback will be
called exactly once.
See also
leptos::watch
fn@crate::watch_throttled
Feature
This function is only available if the crate feature
watch_debounced
is enabled
Types
Source
watch_pausable
Pausable watch
.
Demo
Usage
use leptos::*;
use leptos::logging::log;
use leptos_use::{watch_pausable, WatchPausableReturn};
pub fn Demo() -> impl IntoView {
let (source, set_source) = create_signal("foo".to_string());
let WatchPausableReturn {
stop,
pause,
resume,
..
} = watch_pausable(
move || source.get(),
|v, _, _| {
log!("Changed to {}", v);
},
);
set_source.set("bar".to_string()); // > "Changed to bar"
pause();
set_source.set("foobar".to_string()); // (nothing happens)
resume();
set_source.set("hello".to_string()); // > "Changed to hello"
view! { }
}
There's also watch_pausable_with_options
which takes the same options as watch
.
Server-Side Rendering
On the server this works just fine except if you throttle or debounce in which case the callback
will never be called except if you set immediate
to true
in which case the callback will be
called exactly once.
See also
leptos::watch
Feature
This function is only available if the crate feature
watch_pausable
is enabled
Types
Source
watch_throttled
A throttled version of leptos::watch
.
Demo
Usage
use leptos::*;
use leptos::logging::log;
use leptos_use::watch_throttled;
pub fn Demo() -> impl IntoView {
let (source, set_source) = create_signal(0);
watch_throttled(
move || source.get(),
move |_, _, _| {
log!("changed!");
},
500.0,
);
view! { }
}
This really is only shorthand shorthand for watch_with_options(deps, callback, WatchOptions::default().throttle(ms))
.
Please note that if the current component is cleaned up before the throttled callback is called, the throttled callback will not be called.
There's also watch_throttled_with_options
where you can specify the other watch options (except filter
).
use leptos::*;
use leptos::logging::log;
use leptos_use::{watch_throttled_with_options, WatchThrottledOptions};
pub fn Demo() -> impl IntoView {
let (source, set_source) = create_signal(0);
watch_throttled_with_options(
move || source.get(),
move |_, _, _| {
log!("changed!");
},
500.0,
WatchThrottledOptions::default().leading(true).trailing(false),
);
view! { }
}
Recommended Reading
Server-Side Rendering
On the server the callback
will never be called except if you set immediate
to true
in which case the callback will be
called exactly once.
See also
leptos::watch
fn@crate::watch_debounced
Feature
This function is only available if the crate feature
watch_throttled
is enabled
Types
Source
watch_with_options
whenever
Shorthand for watching a signal to be true
.
Usage
use leptos::*;
use leptos::logging::log;
use leptos_use::whenever;
pub fn Demo() -> impl IntoView {
let (is_ready, set_ready) = create_signal(false);
whenever(move || is_ready.get(), |v, _, _| log!("{}", v));
view! { }
}
Callback Function
Same as fn@crate::watch
, the callback will be called with callback(input, prev_input, prev_return)
.
use leptos::*;
use leptos::logging::log;
use leptos_use::whenever;
pub fn Demo() -> impl IntoView {
let (is_ready, set_ready) = create_signal(false);
whenever(move || is_ready.get(), |value, prev_value, _| {
log!("before: {prev_value:?}; now: {value}");
});
view! { }
}
Computed
Same as fn@crate::watch
, you can pass a getter function to calculate on each change.
use leptos::*;
use leptos::logging::log;
use leptos_use::whenever;
pub fn Demo() -> impl IntoView {
let (counter, set_counter) = create_signal(0);
whenever(
move || counter.get() == 7,
|_, _, _| log!("counter is 7 now!"),
);
view! { }
}
Options
Options and defaults are same as fn@watch_with_options
.
use leptos::*;
use leptos::logging::log;
use leptos_use::{WatchOptions, whenever_with_options};
pub fn Demo() -> impl IntoView {
let (counter, set_counter) = create_signal(0);
whenever_with_options(
move || counter.get() == 7,
|_, _, _| log!("counter is 7 now!"),
WatchOptions::default().immediate(true),
);
view! { }
}
Server-Side Rendering
On the server this works just fine except if you throttle or debounce in which case the callback
will never be called except if you set immediate
to true
in which case the callback will be
called exactly once.
Feature
This function is only available if the crate feature
whenever
is enabled
Source
signal_debounced
Debounce changing of a Signal
value.
Demo
Usage
use leptos::*;
use leptos_use::signal_debounced;
#[component]
fn Demo() -> impl IntoView {
let (input, set_input) = create_signal("");
let debounced: Signal<&'static str> = signal_debounced(input, 1000.0);
view! { }
}
Options
The usual debounce option max_wait
is available.
use leptos::*;
use leptos_use::{signal_debounced_with_options, DebounceOptions};
#[component]
fn Demo() -> impl IntoView {
let (input, set_input) = create_signal("");
let debounced: Signal<&'static str> = signal_debounced_with_options(
input,
1000.0,
DebounceOptions::default().max_wait(Some(500.0))
);
view! { }
}
Recommended Reading
Server-Side Rendering
Internally this uses setTimeout
which is not supported on the server. So usually
a throttled signal on the server will simply be ignored.
Feature
This function is only available if the crate feature
signal_debounced
is enabled
Source
signal_throttled
Throttle changing of a Signal
value.
Demo
Usage
use leptos::*;
use leptos_use::signal_throttled;
#[component]
fn Demo() -> impl IntoView {
let (input, set_input) = create_signal("");
let throttled: Signal<&'static str> = signal_throttled(input, 1000.0);
view! { }
}
Options
The usual throttle options leading
and trailing
are available.
use leptos::*;
use leptos_use::{signal_throttled_with_options, ThrottleOptions};
#[component]
fn Demo() -> impl IntoView {
let (input, set_input) = create_signal("");
let throttled: Signal<&'static str> = signal_throttled_with_options(
input,
1000.0,
ThrottleOptions::default().leading(false).trailing(true)
);
view! { }
}
Recommended Reading
Server-Side Rendering
Internally this uses setTimeout
which is not supported on the server. So usually
a throttled signal on the server will simply be ignored.
Feature
This function is only available if the crate feature
signal_throttled
is enabled
Source
sync_signal
Two-way Signals synchronization.
Note: Please consider first if you can achieve your goals with the "Good Options" described in the Leptos book Only if you really have to, use this function. This is, in effect, the "If you really must..." option.
Demo
Usage
use leptos::*;
use leptos_use::sync_signal;
#[component]
fn Demo() -> impl IntoView {
let (a, set_a) = create_signal(1);
let (b, set_b) = create_signal(2);
let stop = sync_signal((a, set_a), (b, set_b));
logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 1, b: 1
set_b.set(3);
logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 3, b: 3
set_a.set(4);
logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 4, b: 4
view! { }
}
RwSignal
You can mix and match RwSignal
s and Signal
-WriteSignal
pairs.
use leptos::*;
use leptos_use::sync_signal;
#[component]
fn Demo() -> impl IntoView {
let (a, set_a) = create_signal(1);
let (b, set_b) = create_signal(2);
let c_rw = create_rw_signal(3);
let d_rw = create_rw_signal(4);
sync_signal((a, set_a), c_rw);
sync_signal(d_rw, (b, set_b));
sync_signal(c_rw, d_rw);
view! { }
}
One directional
You can synchronize a signal only from left to right or right to left.
use leptos::*;
use leptos_use::{sync_signal_with_options, SyncSignalOptions, SyncDirection};
#[component]
fn Demo() -> impl IntoView {
let (a, set_a) = create_signal(1);
let (b, set_b) = create_signal(2);
let stop = sync_signal_with_options(
(a, set_a),
(b, set_b),
SyncSignalOptions::default().direction(SyncDirection::LeftToRight)
);
set_b.set(3); // doesn't sync
logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 1, b: 3
set_a.set(4);
logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 4, b: 4
view! { }
}
Custom Transform
You can optionally provide custom transforms between the two signals.
use leptos::*;
use leptos_use::{sync_signal_with_options, SyncSignalOptions};
#[component]
fn Demo() -> impl IntoView {
let (a, set_a) = create_signal(10);
let (b, set_b) = create_signal(2);
let stop = sync_signal_with_options(
(a, set_a),
(b, set_b),
SyncSignalOptions::with_transforms(
|left| *left * 2,
|right| *right / 2,
),
);
logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 10, b: 20
set_b.set(30);
logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 15, b: 30
view! { }
}
Different Types
SyncSignalOptions::default()
is only defined if the two signal types are identical.
Otherwise, you have to initialize the options with with_transforms
or with_assigns
instead
of default
.
use leptos::*;
use leptos_use::{sync_signal_with_options, SyncSignalOptions};
use std::str::FromStr;
#[component]
fn Demo() -> impl IntoView {
let (a, set_a) = create_signal("10".to_string());
let (b, set_b) = create_signal(2);
let stop = sync_signal_with_options(
(a, set_a),
(b, set_b),
SyncSignalOptions::with_transforms(
|left: &String| i32::from_str(left).unwrap_or_default(),
|right: &i32| right.to_string(),
),
);
view! { }
}
use leptos::*;
use leptos_use::{sync_signal_with_options, SyncSignalOptions};
use std::str::FromStr;
#[derive(Clone)]
pub struct Foo {
bar: i32,
}
#[component]
fn Demo() -> impl IntoView {
let (a, set_a) = create_signal(Foo { bar: 10 });
let (b, set_b) = create_signal(2);
let stop = sync_signal_with_options(
(a, set_a),
(b, set_b),
SyncSignalOptions::with_assigns(
|b: &mut i32, a: &Foo| *b = a.bar,
|a: &mut Foo, b: &i32| a.bar = *b,
),
);
view! { }
}
Feature
This function is only available if the crate feature
sync_signal
is enabled
Types
Source
use_sorted
Reactive sort of iterable
Demo
Usage
use leptos::*;
use leptos_use::use_sorted;
#[component]
fn Demo() -> impl IntoView {
let source = vec![10, 3, 5, 7, 2, 1, 8, 6, 9, 4];
let sorted = use_sorted(source); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
view! { }
}
You can also sort by key or with a compare function.
use leptos::*;
use leptos_use::{use_sorted_by, use_sorted_by_key};
#[derive(Clone, PartialEq)]
pub struct Person {
pub name: String,
pub age: u16,
}
#[component]
fn Demo() -> impl IntoView {
let source = vec![
Person {
name: "John".to_string(),
age: 40,
},
Person {
name: "Jane".to_string(),
age: 20,
},
Person {
name: "Joe".to_string(),
age: 30,
},
Person {
name: "Jenny".to_string(),
age: 22,
},
];
// sort by key
let sorted = use_sorted_by_key(
source.clone(),
|person| person.age,
);
// sort with compare function
let sorted = use_sorted_by(
source,
|p1, p2| p1.age.cmp(&p2.age),
);
view! { }
}
Please note that these two ways of sorting are equivalent.
Feature
This function is only available if the crate feature
use_sorted
is enabled
Source
header
Get the value of the header with the given name.
This function is only meant to be used on the server.
So it is only defined when the feature "ssr"
is enabled together with one of the
features "axum"
, "actix"
or "spin"
.
Example
use leptos_use::utils::header;
let content_len = header(http::header::CONTENT_LENGTH);
Feature
This function is only available if the crate feature
utils/header
is enabled
Source
is_err
Reactive Result::is_err()
.
Usage
use leptos::*;
use leptos_use::is_err;
#[component]
fn Demo() -> impl IntoView {
let (example, set_example) = create_signal(
if js_sys::Math::random() < 0.5 { Ok("Example") } else { Err(()) }
);
let is_error = is_err(example);
view! { }
}
Feature
This function is only available if the crate feature
is_err
is enabled
Source
is_none
Reactive Option::is_none()
.
Usage
use leptos::*;
use leptos_use::is_none;
#[component]
fn Demo() -> impl IntoView {
let (example, set_example) = create_signal(
if js_sys::Math::random() < 0.5 { Some("Example") } else { None }
);
let is_empty = is_none(example);
view! { }
}
Feature
This function is only available if the crate feature
is_none
is enabled
Source
is_ok
Reactive Result::is_ok()
.
Usage
use leptos::*;
use leptos_use::is_ok;
#[component]
fn Demo() -> impl IntoView {
let (example, set_example) = create_signal(
if js_sys::Math::random() < 0.5 { Ok("Example") } else { Err(()) }
);
let is_ok = is_ok(example);
view! { }
}
Feature
This function is only available if the crate feature
is_ok
is enabled
Source
is_some
Reactive Option::is_some()
.
Usage
use leptos::*;
use leptos_use::is_some;
#[component]
fn Demo() -> impl IntoView {
let (example, set_example) = create_signal(
if js_sys::Math::random() < 0.5 { Some("Example") } else { None }
);
let not_empty = is_some(example);
view! { }
}
Feature
This function is only available if the crate feature
is_some
is enabled
Source
use_cycle_list
Cycle through a list of items.
Demo
Usage
use leptos::*;
use leptos::logging::log;
use leptos_use::{use_cycle_list, UseCycleListReturn};
#[component]
fn Demo() -> impl IntoView {
let UseCycleListReturn { state, next, prev, .. } = use_cycle_list(
vec!["Dog", "Cat", "Lizard", "Shark", "Whale", "Dolphin", "Octopus", "Seal"]
);
log!("{}", state.get()); // "Dog"
prev();
log!("{}", state.get()); // "Seal"
view! { }
}
Feature
This function is only available if the crate feature
use_cycle_list
is enabled
Types
Source
use_debounce_fn
Debounce execution of a function.
Debounce is an overloaded waiter: If you keep asking him your requests will be ignored until you stop and give him some time to think about your latest inquiry.
Demo
Usage
use leptos::*;
use leptos::ev::resize;
use leptos_use::use_debounce_fn;
#[component]
fn Demo() -> impl IntoView {
let mut debounced_fn = use_debounce_fn(
|| {
// do something
},
1000.0,
);
window_event_listener(resize, move |_| { debounced_fn(); });
view! { }
}
Please note that if the current component is cleaned up before the throttled callback is called, the throttled callback will not be called.
You can also pass options to use_debounce_fn_with_options
with a maximum wait time, similar to
lodash debounce.
use leptos::*;
use leptos::ev::resize;
use leptos_use::use_debounce_fn_with_options;
use leptos_use::utils::DebounceOptions;
#[component]
fn Demo() -> impl IntoView {
let mut debounced_fn = use_debounce_fn_with_options(
|| {
// do something
},
1000.0,
DebounceOptions::default()
.max_wait(Some(5000.0)),
);
window_event_listener(resize, move |_| { debounced_fn(); });
view! { }
}
Currently there is no way to use a function with a return value. Please open an issue if you need this.
If you want to throttle a function that takes an argument there are also the versions
use_debounce_fn_with_arg
and use_debounce_fn_with_arg_and_options
.
Recommended Reading
Server-Side Rendering
Internally this uses setTimeout
which is not supported on the server. So usually calling
a debounced function on the server will simply be ignored.
Feature
This function is only available if the crate feature
use_debounce_fn
is enabled
Source
use_derive_signal!
Macro to easily create helper functions that derive a signal using a piece of code.
See is_ok
or use_to_string
as examples.
use_supported
SSR compatibe is_supported
Usage
use leptos::*;
use leptos_use::{use_supported, js};
use wasm_bindgen::JsValue;
pub fn Demo() -> impl IntoView {
let is_supported = use_supported(
|| js!("getBattery" in &window().navigator())
);
if is_supported.get() {
// do something
}
view! { }
}
Feature
This function is only available if the crate feature
use_supported
is enabled
Source
use_throttle_fn
Throttle execution of a function. Especially useful for rate limiting execution of handlers on events like resize and scroll.
Throttle is a spring that throws balls: After a ball flies out it needs some time to shrink back, so it cannot throw any more balls until it's ready.
Demo
Usage
use leptos::*;
use leptos_use::use_throttle_fn;
#[component]
fn Demo() -> impl IntoView {
let mut throttled_fn = use_throttle_fn(
|| {
// do something, it will be called at most 1 time per second
},
1000.0,
);
view! {
<button on:click=move |_| { throttled_fn(); }>
"Smash me!"
</button>
}
}
Please note that if the current component is cleaned up before the throttled callback is called, the throttled callback will not be called.
You can provide options when you use use_throttle_fn_with_options
.
use leptos::*;
use leptos_use::{ThrottleOptions, use_throttle_fn_with_options};
#[component]
fn Demo() -> impl IntoView {
let throttled_fn = use_throttle_fn_with_options(
|| {
// do something, it will be called at most 1 time per second
},
1000.0,
ThrottleOptions::default()
.leading(true)
.trailing(true),
);
view! { }
}
If you want to throttle a function that takes an argument there are also the versions
use_throttle_fn_with_arg
and use_throttle_fn_with_arg_and_options
.
Recommended Reading
Server-Side Rendering
Internally this uses setTimeout
which is not supported on the server. So usually calling
a throttled function on the server will simply be ignored.
Feature
This function is only available if the crate feature
use_throttle_fn
is enabled
Source
use_to_string
Reactive ToString::to_string()
.
Usage
use leptos::*;
use leptos_use::use_to_string;
#[component]
fn Demo() -> impl IntoView {
let (number, set_number) = create_signal(3.14_f64);
let str = use_to_string::<_, f64>(number);
view! { }
}
Feature
This function is only available if the crate feature
use_to_string
is enabled
Source
use_toggle
A boolean switcher with utility functions.
Demo
Usage
use leptos::*;
use leptos_use::{use_toggle, UseToggleReturn};
#[component]
fn Demo() -> impl IntoView {
let UseToggleReturn { toggle, value, set_value } = use_toggle(true);
view! { }
}
See also
Feature
This function is only available if the crate feature
use_toggle
is enabled
Types
Source
use_intl_number_format
Reactive Intl.NumberFormat
.
Demo
Usage
In basic use without specifying a locale, a formatted string in the default locale and with default options is returned.
use leptos::*;
use leptos_use::{use_intl_number_format, UseIntlNumberFormatOptions};
#[component]
fn Demo() -> impl IntoView {
let (number, set_number) = create_signal(3500);
let number_format = use_intl_number_format(UseIntlNumberFormatOptions::default());
let formatted = number_format.format::<u16>(number); // "3,500" if in US English locale
view! { }
}
Using locales
This example shows some of the variations in localized number formats. In order to get the format
of the language used in the user interface of your application, make sure to specify that language
(and possibly some fallback languages) using the locales
argument:
use leptos::*;
use leptos_use::{use_intl_number_format, UseIntlNumberFormatOptions};
#[component]
fn Demo() -> impl IntoView {
let number = 123456.789_f32;
// German uses comma as decimal separator and period for thousands
let number_format = use_intl_number_format(
UseIntlNumberFormatOptions::default().locale("de-DE"),
);
let formatted = number_format.format(number); // 123.456,789
// Arabic in most Arabic speaking countries uses real Arabic digits
let number_format = use_intl_number_format(
UseIntlNumberFormatOptions::default().locale("ar-EG"),
);
let formatted = number_format.format(number); // Ω‘Ω’Ω£Ω€Ω₯Ω¦Ω«Ω§Ω¨Ω©
// India uses thousands/lakh/crore separators
let number_format = use_intl_number_format(
UseIntlNumberFormatOptions::default().locale("en-IN"),
);
let formatted = number_format.format(number); // 1,23,456.789
// the nu extension key requests a numbering system, e.g. Chinese decimal
let number_format = use_intl_number_format(
UseIntlNumberFormatOptions::default().locale("zh-Hans-CN-u-nu-hanidec"),
);
let formatted = number_format.format(number); // δΈδΊδΈ,εδΊε
.δΈε
«δΉ
// when requesting a language that may not be supported, such as
// Balinese, include a fallback language, in this case Indonesian
let number_format = use_intl_number_format(
UseIntlNumberFormatOptions::default().locales(vec!["ban".to_string(), "id".to_string()]),
);
let formatted = number_format.format(number); // 123.456,789
view! { }
}
Using options
The results can be customized in multiple ways.
use leptos::*;
use leptos_use::{NumberStyle, UnitDisplay, use_intl_number_format, UseIntlNumberFormatOptions};
#[component]
fn Demo() -> impl IntoView {
let number = 123456.789_f64;
// request a currency format
let number_format = use_intl_number_format(
UseIntlNumberFormatOptions::default()
.locale("de-DE")
.style(NumberStyle::Currency)
.currency("EUR"),
);
let formatted = number_format.format(number); // 123.456,79 β¬
// the Japanese yen doesn't use a minor unit
let number_format = use_intl_number_format(
UseIntlNumberFormatOptions::default()
.locale("ja-JP")
.style(NumberStyle::Currency)
.currency("JPY"),
);
let formatted = number_format.format(number); // οΏ₯123,457
// limit to three significant digits
let number_format = use_intl_number_format(
UseIntlNumberFormatOptions::default()
.locale("en-IN")
.maximum_significant_digits(3),
);
let formatted = number_format.format(number); // 1,23,000
// Formatting with units
let number_format = use_intl_number_format(
UseIntlNumberFormatOptions::default()
.locale("pt-PT")
.style(NumberStyle::Unit)
.unit("kilometer-per-hour"),
);
let formatted = number_format.format(50); // 50 km/h
let number_format = use_intl_number_format(
UseIntlNumberFormatOptions::default()
.locale("en-GB")
.style(NumberStyle::Unit)
.unit("liter")
.unit_display(UnitDisplay::Long),
);
let formatted = number_format.format(16); // 16 litres
view! { }
}
For an exhaustive list of options see UseIntlNumberFormatOptions
.
Formatting ranges
Apart from the format
method, the format_range
method can be used to format a range of numbers.
Please see UseIntlNumberFormatReturn::format_range
for details.
Server-Side Rendering
Since Intl.NumberFormat
is a JavaScript API it is not available on the server. That's why
it falls back to a simple call to format!()
on the server.
Feature
This function is only available if the crate feature
use_intl_number_format
is enabled
Types
enum CompactDisplay
enum CurrencyDisplay
enum CurrencySign
enum LocaleMatcher
enum Notation
enum SignDisplay
enum NumberStyle
enum UnitDisplay
enum NumberGrouping
enum RoundingMode
enum RoundingPriority
enum TrailingZeroDisplay
struct UseIntlNumberFormatOptions
Source
use_locale
Reactive locale matching.
Returns the first matching locale given by fn@crate::use_locales
that is also found in
the supported
list. In case there is no match, then the first locale in supported
will be
returned.
If
supported
is empty, this function will panic!
Matching is done by using the fn@unic_langid::LanguageIdentifier::matches
method.
Demo
Usage
use leptos::*;
use leptos_use::use_locale;
use unic_langid::langid_slice;
#[component]
fn Demo() -> impl IntoView {
let locale = use_locale(langid_slice!["en", "de", "fr"]);
view! { }
}
Server-Side Rendering
Feature
This function is only available if the crate feature
use_locale
is enabled
Source
use_locales
Reactive locales.
If called on the client-side this function returns the value of
navigator.languages
and listens for changes to that property.
See "Server-Side Rendering" below.
Demo
Usage
use leptos::*;
use leptos_use::use_locales;
#[component]
fn Demo() -> impl IntoView {
let locales = use_locales();
view! { }
}
Server-Side Rendering
On the server this returns the parsed value of the accept-language
header.
If you're using
axum
you have to enable the"axum"
feature in your Cargo.toml. In case it'sactix-web
enable the feature"actix"
, forspin
enable"spin"
.
Bring your own header
In case you're neither using Axum, Actix nor Spin, or the default implementation is not to your liking,
you can provide your own way of reading the language header value using the option
crate::UseLocalesOptions::ssr_lang_header_getter
.
Feature
This function is only available if the crate feature
use_locales
is enabled
Types
Source
use_abs
Reactive abs()
.
Demo
Usage
use leptos::*;
use leptos_use::math::use_abs;
#[component]
fn Demo() -> impl IntoView {
let (value, set_value) = create_signal(-32.25);
let result: Signal<f64> = use_abs(value); // 32.25
assert_eq!(result.get(), 32.25);
view! { }
}
Feature
This function is only available if the crate feature
math
is enabled
Source
use_and
Reactive AND
condition.
Demo
Usage
use leptos::*;
use leptos_use::math::use_and;
#[component]
fn Demo() -> impl IntoView {
let (a, set_a) = create_signal(true);
let (b, set_b) = create_signal(false);
let a_and_b = use_and(a, b);
view! { }
}
Feature
This function is only available if the crate feature
math
is enabled
Source
use_ceil
Reactive ceil()
.
Demo
Usage
use leptos::*;
use leptos_use::math::use_ceil;
#[component]
fn Demo() -> impl IntoView {
let (value, set_value) = create_signal(44.15);
let result: Signal<f64> = use_ceil(value); // 45
assert_eq!(result.get(), 45.0);
view! { }
}
Feature
This function is only available if the crate feature
math
is enabled
Source
use_floor
Reactive floor()
.
Demo
Usage
use leptos::*;
use leptos_use::math::use_floor;
#[component]
fn Demo() -> impl IntoView {
let (value, set_value) = create_signal(45.95);
let result: Signal<f64> = use_floor(value); // 45
assert_eq!(result.get(), 45.0);
view! { }
}
Feature
This function is only available if the crate feature
math
is enabled
Source
use_max
Reactive max()
.
Works with any container that implements IntoIterator
(Vec
, HashSet
, ...)
with any elements that implement PartialOrd
and Clone
(floats, ints, strings, ...).
If the container is empty or only contains non comparable values like NaN
, it returns None
.
Otherwise it returns the Some(<largest value>)
in the container.
Usage
use leptos::*;
use leptos_use::math::use_max;
#[component]
fn Demo() -> impl IntoView {
let (values, set_values) = create_signal(vec![1.0, 2.0, 3.0, f32::NAN, 4.0, 5.0]);
let result = use_max::<Vec<f32>, _, _>(values); // Some(5.0)
assert_eq!(result.get(), Some(5.0));
view! { }
}
Feature
This function is only available if the crate feature
math
is enabled
Source
use_min
Reactive min()
.
Works with any container that implements IntoIterator
(Vec
, HashSet
, ...)
with any elements that implement PartialOrd
and Clone
(floats, ints, strings, ...).
If the container is empty or only contains non comparable values like NaN
, it returns None
.
Otherwise it returns the Some(<smallest value>)
in the container.
Usage
use leptos::*;
use leptos_use::math::use_min;
#[component]
fn Demo() -> impl IntoView {
let (values, set_values) = create_signal(vec![1.0, 2.0, 3.0, f32::NAN, 4.0, 5.0]);
let result = use_min::<Vec<f32>, _, _>(values); // Some(1.0)
assert_eq!(result.get(), Some(1.0));
view! { }
}
Feature
This function is only available if the crate feature
math
is enabled
Source
use_not
Reactive NOT
condition.
Demo
Usage
use leptos::*;
use leptos_use::math::use_not;
#[component]
fn Demo() -> impl IntoView {
let (a, set_a) = create_signal(true);
let not_a = use_not(a);
view! { }
}
See also
Feature
This function is only available if the crate feature
math
is enabled
Source
use_or
Reactive OR
condition.
Demo
Usage
use leptos::*;
use leptos_use::math::use_or;
#[component]
fn Demo() -> impl IntoView {
let (a, set_a) = create_signal(true);
let (b, set_b) = create_signal(false);
let a_or_b = use_or(a, b);
view! { }
}
Feature
This function is only available if the crate feature
math
is enabled
Source
use_round
Reactive round()
.
Demo
Usage
use leptos::*;
use leptos_use::math::use_round;
#[component]
fn Demo() -> impl IntoView {
let (value, set_value) = create_signal(45.95);
let result: Signal<f64> = use_round(value); // 46
assert_eq!(result.get(), 46.0);
view! { }
}
Feature
This function is only available if the crate feature
math
is enabled