mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
feat: 0.7 query signals
This commit is contained in:
parent
f7ee0c4764
commit
a32c71539d
7 changed files with 75 additions and 38 deletions
|
@ -10,8 +10,6 @@ lto = true
|
|||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
leptos_router = { path = "../../router", features = [] }
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
use leptos::prelude::*;
|
||||
use leptos_router::*;
|
||||
use leptos_router::hooks::query_signal;
|
||||
|
||||
/// A simple counter component.
|
||||
///
|
||||
/// You can use doc comments like this to document your component.
|
||||
#[component]
|
||||
pub fn SimpleQueryCounter() -> impl IntoView {
|
||||
let (count, set_count) = create_query_signal::<i32>("count");
|
||||
let (count, set_count) = query_signal::<i32>("count");
|
||||
let clear = move |_| set_count.set(None);
|
||||
let decrement = move |_| set_count.set(Some(count.get().unwrap_or(0) - 1));
|
||||
let increment = move |_| set_count.set(Some(count.get().unwrap_or(0) + 1));
|
||||
|
||||
let (msg, set_msg) = create_query_signal::<String>("message");
|
||||
let (msg, set_msg) = query_signal::<String>("message");
|
||||
let update_msg = move |ev| {
|
||||
let new_msg = event_target_value(&ev);
|
||||
if new_msg.is_empty() {
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
use counter_url_query::SimpleQueryCounter;
|
||||
use leptos::prelude::*;
|
||||
use leptos_router::*;
|
||||
use leptos_router::components::Router;
|
||||
|
||||
pub fn main() {
|
||||
_ = console_log::init_with_level(log::Level::Debug);
|
||||
console_error_panic_hook::set_once();
|
||||
mount_to_body(|| {
|
||||
leptos::mount::mount_to_body(|| {
|
||||
view! {
|
||||
<Router>
|
||||
<Routes>
|
||||
<Route path="" view=SimpleQueryCounter />
|
||||
</Routes>
|
||||
<SimpleQueryCounter/>
|
||||
</Router>
|
||||
}
|
||||
})
|
||||
|
|
|
@ -25,6 +25,7 @@ paste = "1"
|
|||
once_cell = "1"
|
||||
send_wrapper = "0.6"
|
||||
thiserror = "1"
|
||||
percent-encoding = { version = "2.3", optional = true }
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3"
|
||||
|
@ -56,7 +57,7 @@ features = [
|
|||
|
||||
[features]
|
||||
tracing = ["dep:tracing"]
|
||||
ssr = []
|
||||
ssr = ["dep:percent-encoding"]
|
||||
nightly = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
|
|
|
@ -4,14 +4,42 @@ use crate::{
|
|||
navigate::NavigateOptions,
|
||||
params::{Params, ParamsError, ParamsMap},
|
||||
};
|
||||
use leptos::oco::Oco;
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, Memo},
|
||||
owner::use_context,
|
||||
signal::{ArcRwSignal, ReadSignal},
|
||||
traits::{Get, With},
|
||||
traits::{Get, GetUntracked, With},
|
||||
wrappers::write::SignalSetter,
|
||||
};
|
||||
use std::str::FromStr;
|
||||
use tachys::renderer::Renderer;
|
||||
/*
|
||||
|
||||
#[track_caller]
|
||||
#[deprecated = "This has been renamed to `query_signal` to match Rust naming \
|
||||
conventions."]
|
||||
pub fn create_query_signal<T>(
|
||||
key: impl Into<Oco<'static, str>>,
|
||||
) -> (Memo<Option<T>>, SignalSetter<Option<T>>)
|
||||
where
|
||||
T: FromStr + ToString + PartialEq + Send + Sync,
|
||||
{
|
||||
query_signal(key)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
#[deprecated = "This has been renamed to `query_signal_with_options` to mtch \
|
||||
Rust naming conventions."]
|
||||
pub fn create_query_signal_with_options<T>(
|
||||
key: impl Into<Oco<'static, str>>,
|
||||
nav_options: NavigateOptions,
|
||||
) -> (Memo<Option<T>>, SignalSetter<Option<T>>)
|
||||
where
|
||||
T: FromStr + ToString + PartialEq + Send + Sync,
|
||||
{
|
||||
query_signal_with_options(key, nav_options)
|
||||
}
|
||||
|
||||
/// Constructs a signal synchronized with a specific URL query parameter.
|
||||
///
|
||||
/// The function creates a bidirectional sync mechanism between the state encapsulated in a signal and a URL query parameter.
|
||||
|
@ -26,12 +54,12 @@ use tachys::renderer::Renderer;
|
|||
/// The URL parameter can be cleared by setting the signal to `None`.
|
||||
///
|
||||
/// ```rust
|
||||
/// use leptos::*;
|
||||
/// use leptos_router::*;
|
||||
/// use leptos::prelude::*;
|
||||
/// use leptos_router::hooks::query_signal;
|
||||
///
|
||||
/// #[component]
|
||||
/// pub fn SimpleQueryCounter() -> impl IntoView {
|
||||
/// let (count, set_count) = create_query_signal::<i32>("count");
|
||||
/// let (count, set_count) = query_signal::<i32>("count");
|
||||
/// let clear = move |_| set_count.set(None);
|
||||
/// let decrement =
|
||||
/// move |_| set_count.set(Some(count.get().unwrap_or(0) - 1));
|
||||
|
@ -49,29 +77,29 @@ use tachys::renderer::Renderer;
|
|||
/// }
|
||||
/// ```
|
||||
#[track_caller]
|
||||
pub fn create_query_signal<T>(
|
||||
pub fn query_signal<T>(
|
||||
key: impl Into<Oco<'static, str>>,
|
||||
) -> (Memo<Option<T>>, SignalSetter<Option<T>>)
|
||||
where
|
||||
T: FromStr + ToString + PartialEq,
|
||||
T: FromStr + ToString + PartialEq + Send + Sync,
|
||||
{
|
||||
create_query_signal_with_options::<T>(key, NavigateOptions::default())
|
||||
query_signal_with_options::<T>(key, NavigateOptions::default())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn create_query_signal_with_options<T>(
|
||||
pub fn query_signal_with_options<T>(
|
||||
key: impl Into<Oco<'static, str>>,
|
||||
nav_options: NavigateOptions,
|
||||
) -> (Memo<Option<T>>, SignalSetter<Option<T>>)
|
||||
where
|
||||
T: FromStr + ToString + PartialEq,
|
||||
T: FromStr + ToString + PartialEq + Send + Sync,
|
||||
{
|
||||
let mut key: Oco<'static, str> = key.into();
|
||||
let query_map = use_query_map();
|
||||
let navigate = use_navigate();
|
||||
let location = use_location();
|
||||
|
||||
let get = create_memo({
|
||||
let get = Memo::new({
|
||||
let key = key.clone_inplace();
|
||||
move |_| {
|
||||
query_map
|
||||
|
@ -106,7 +134,7 @@ pub(crate) fn has_router() -> bool {
|
|||
|
||||
/// Returns the current [`RouterContext`], containing information about the router's state.
|
||||
#[track_caller]
|
||||
pub fn use_router() -> RouterContext {
|
||||
pub(crate) fn use_router() -> RouterContext {
|
||||
if let Some(router) = use_context::<RouterContext>() {
|
||||
router
|
||||
} else {
|
||||
|
@ -116,7 +144,7 @@ pub fn use_router() -> RouterContext {
|
|||
);
|
||||
panic!("You must call use_router() within a <Router/> component");
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
/// Returns the current [`Location`], which contains reactive variables
|
||||
#[track_caller]
|
||||
|
|
|
@ -61,6 +61,21 @@ impl Url {
|
|||
provide_context(ServerActionError::new(path, err))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn escape(s: &str) -> String {
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
{
|
||||
js_sys::encode_uri_component(s).as_string().unwrap()
|
||||
}
|
||||
#[cfg(feature = "ssr")]
|
||||
{
|
||||
percent_encoding::utf8_percent_encode(
|
||||
s,
|
||||
percent_encoding::NON_ALPHANUMERIC,
|
||||
)
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A reactive description of the current URL, containing equivalents to the local parts of
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::{borrow::Cow, str::FromStr, sync::Arc};
|
||||
use crate::location::{unescape, Url};
|
||||
use std::{borrow::Cow, mem, str::FromStr, sync::Arc};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -17,18 +18,19 @@ impl ParamsMap {
|
|||
Self(Vec::with_capacity(capacity))
|
||||
}
|
||||
|
||||
/*
|
||||
/// Inserts a value into the map.
|
||||
#[inline(always)]
|
||||
pub fn insert(&mut self, key: String, value: String) -> Option<String> {
|
||||
use crate::history::url::unescape;
|
||||
let value = unescape(&value);
|
||||
self.0.insert(key, value)
|
||||
|
||||
if let Some(prev) = self.0.iter().position(|(k, _)| k == &key) {
|
||||
return Some(mem::replace(&mut self.0[prev].1, value));
|
||||
}
|
||||
|
||||
self.0.push((key.into(), value));
|
||||
None
|
||||
}
|
||||
*/
|
||||
|
||||
/// Gets an owned value from the map.
|
||||
#[inline(always)]
|
||||
pub fn get(&self, key: &str) -> Option<String> {
|
||||
self.0
|
||||
.iter()
|
||||
|
@ -36,7 +38,6 @@ impl ParamsMap {
|
|||
}
|
||||
|
||||
/// Gets a referenc to a value from the map.
|
||||
#[inline(always)]
|
||||
pub fn get_str(&self, key: &str) -> Option<&str> {
|
||||
self.0
|
||||
.iter()
|
||||
|
@ -54,17 +55,15 @@ impl ParamsMap {
|
|||
None
|
||||
}
|
||||
|
||||
/*
|
||||
/// Converts the map to a query string.
|
||||
pub fn to_query_string(&self) -> String {
|
||||
use crate::history::url::escape;
|
||||
let mut buf = String::new();
|
||||
if !self.0.is_empty() {
|
||||
buf.push('?');
|
||||
for (k, v) in &self.0 {
|
||||
buf.push_str(&escape(k));
|
||||
buf.push_str(&Url::escape(k));
|
||||
buf.push('=');
|
||||
buf.push_str(&escape(v));
|
||||
buf.push_str(&Url::escape(v));
|
||||
buf.push('&');
|
||||
}
|
||||
if buf.len() > 1 {
|
||||
|
@ -73,7 +72,6 @@ impl ParamsMap {
|
|||
}
|
||||
buf
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
impl<K, V> FromIterator<(K, V)> for ParamsMap
|
||||
|
|
Loading…
Reference in a new issue