Leptos-Use Guide

Leptos-Use – Collection of essential Leptos utilities

Collection of essential Leptos utilities

Inspired by React-Use / VueUse / SolidJS-USE

Crates.io SSR Docs & Demos 87 Functions

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 returned None.

[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 for use_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 before open 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 messages
  • SyncSignalOptions 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 the vibrate option (thanks to @hcandelaria).
  • UseDocument now supports a whole bunch of methods more from document (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 uses unic_langid::LanguageIdentifier and proper locale matching (thanks to @mondeja).
  • Removed UseMouseEventExtractorDefault and reworked UseMouseCoordType (thanks to @carloskiki)
  • use_preferred_dark and use_color_mode now try to read the Sec-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 options renotify, silent and image (thanks to @hcandelaria).
  • sync_signal no supports the options assign_ltr and assign_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>.
    • There is now an OptionCodec wrapper that allows to wrap any string codec that encodes T to encode Option<T>.
      • Use it like this: OptionCodec<FromToStringCodec<f64>>.
  • ElementMaybeSignal is now implemented for websys::HtmlElement (thanks to @blorbb).

  • UseStorageOptions now has delay_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 to true.

  • 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 and UseEventSourceOptions no longer accept a codec 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 and Decoder. The trait StringCodec is gone. The methods are now associated methods and their params now always take references.
    • JsonCodec has been renamed to JsonSerdeCodec.
    • The feature to enable this codec is now called json_serde instead of just serde.
    • 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 to UseWebSocketOptions (uppercase S) to be consistent with the return type.
    • UseWebSocketOptions::reconnect_limit and UseEventSourceOptions::reconnect_limit is now ReconnectLimit instead of u64. Use ReconnectLimit::Infinite for infinite retries or ReconnectLimit::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 an Option<T> which is decoded using the codec.
      • UseWebSocketReturn::send_bytes and UseWebSocketReturn::message_bytes are gone.
      • UseWebSocketOptions::on_message and UseWebSocketOptions::on_message_bytes have been renamed to on_message_raw and on_message_raw_bytes.
      • The new UseWebSocketOptions::on_message takes a &T.
      • UseWebSocketOptions::on_error now takes a UseWebSocketError instead of a web_sys::Event.
  • use_storage now always saves the default value to storage if the key doesn't exist yet.
  • Renamed BreakpointsSematic to BreakpointsSemantic and breakpoints_sematic to breakpoints_semantic (note the n) (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 with wasm32. You can enable wasm_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's max-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's send... 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 to StringCodec and has been moved to util::StringCodec.
    • The struct StringCodec has been renamed to FromToStringCodec and has been moved to util::FromToStringCodec.
    • The structs JsonCodec and ProstCodec have been moved to util as well.
  • 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 signals x, y, and source_type are now of type Signal<f64> instead of ReadSignal<f64>.
  • You can now convert leptos::html::HtmlElement<T> into Element(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 methods query_selector and query_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 use Codecs instead of always requiring serde.
    • This also removes the feature storage
    • By default the StringCodec is used which relies on types implementing FromString + ToString
    • If you want to use JsonCodec you have to enable the feature serde
    • If you want to use ProstCodec (new!) you have to enable the feature prost.
  • (@feral-dot-io) The Rust flag --cfg=web_sys_unstable_apis is not needed anymore since relevant web_sys APIs are now stable. This affects in particular
    • use_element_size
    • use_resize_observer

Fixes πŸ•

  • use_raf_fn and use_timestamp no longer spam warnings because of getting signals outside of reactive contexts.
  • use_infinite_scroll no longer calls the callback twice for the same event
  • use_scroll now uses try_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 and ElementsMaybeSignal is now SSR safe.
    • This fixes specifically use_color_mode to work on the server.

[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 returns impl Fn(T) + Clone instead of Box<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 for use_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 of leptos::watch and will be removed in a future release. watch_with_options will continue to exist.
  • use_event_listener_with_options now takes a UseEventListenerOptions instead of a web_sys::AddEventListenerOptions.
  • use_mutation_observer_with_options now takes a UseMutationObserverOptions instead of a web_sys::MutationObserverInit.
  • use_websocket:
    • takes now a &str instead of a String as its url parameter.
    • same for the returned send method.
    • The ready_state return type is now renamed to ConnectionReadyState instead of UseWebSocketReadyState.
    • The returned signals ready_state, message, message_bytes have now the type Signal<...> instead of ReadSignal<...> to make them more consistent with other functions.
    • The options reconnect_limit and reconnect_interval now take a u64 instead of Option<u64> to improve DX.
    • The option manual has been renamed to immediate to make it more consistent with other functions. To port please note that immediate is the inverse of manual (immediate = !manual).
    • Added documentation how pass it ergonomically as context.
  • use_color_mode:
    • The optional on_changed handler parameters have changed slightly. Please refer to the docs for more details.
  • 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 synchronized RwSignal 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 return Signal.
    • 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 for leptos.

[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 a stable 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 the nightly feature only on leptos directly. No change is required for leptos-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 a Box<dyn Fn()> but a impl Fn() + Clone

Changes πŸ”₯

  • You can now specify a &str or Signal<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 accept immediate as a direct argument anymore. This is only provided by the option variant.
  • watch has now variant watch_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

Elements

Browser

Intl

Sensors

Network

Animation

Watch

Utilities

Math

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

Source β€’ Docs

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

Source β€’ Docs

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.

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Docs

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

Source β€’ Demo β€’ Docs

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 Signals that are always 0.0.

Feature

This function is only available if the crate feature use_window_scroll is enabled

Source

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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.

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

Source

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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! { }
}

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 or actix feature as described in fn@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's actix-web enable the feature "actix", for spin 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.

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

Source β€’ Demo β€’ Docs

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.

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's actix-web enable the feature "actix", for spin 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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Docs

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's actix-web enable the feature "actix", for spin 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

Source β€’ Docs

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's actix-web enable the feature "actix", for spin 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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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-optrigger_resize`.

Feature

This function is only available if the crate feature use_textarea_autosize is enabled

Types

Source

Source β€’ Demo β€’ Docs

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

Source

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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 Signals with the initial_values.

Feature

This function is only available if the crate feature use_mouse is enabled

Types

Source

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Docs

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 PageRelative UrlResolved Url
http://example.com/some/where/api/wsws://example.com/api/ws
https://example.com/some/where/api/wswss://example.com/api/ws
https://example.com/some/whereapi/wswss://example.com/some/where/api/ws
https://example.com/some/where//otherdomain.com/api/wswss://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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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! { }
}

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

Feature

This function is only available if the crate feature watch_debounced is enabled

Types

Source

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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! { }
}

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

Feature

This function is only available if the crate feature watch_throttled is enabled

Types

Source

Source β€’ Demo β€’ Docs

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

Source β€’ Docs

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! { }
}

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

Source β€’ Demo β€’ Docs

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! { }
}

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

Source β€’ Demo β€’ Docs

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 RwSignals 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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Docs

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

Source β€’ Docs

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

Source β€’ Docs

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

Source β€’ Docs

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

Source β€’ Docs

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

Source β€’ Demo β€’ Docs

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.

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

Source β€’ Demo β€’ Docs

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

Source β€’ Docs

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.

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

Source β€’ Demo β€’ Docs

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

Source β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source

Source β€’ Demo β€’ Docs

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

See fn@crate::use_locales

Feature

This function is only available if the crate feature use_locale is enabled

Source

Source β€’ Demo β€’ Docs

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's actix-web enable the feature "actix", for spin 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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Docs

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

Source β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source β€’ Demo β€’ Docs

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

Source

Source β€’ Demo β€’ Docs