Added the ability to pass state through a link. (#3358)

* state-for-link

* S generic as last generic

* state as last clone
This commit is contained in:
Mikita Bykau 2023-08-14 15:13:00 +03:00 committed by GitHub
parent 05fc4cc819
commit 46bbb0cfe5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -9,10 +9,11 @@ use crate::{utils, Routable};
/// Props for [`Link`] /// Props for [`Link`]
#[derive(Properties, Clone, PartialEq)] #[derive(Properties, Clone, PartialEq)]
pub struct LinkProps<R, Q = ()> pub struct LinkProps<R, Q = (), S = ()>
where where
R: Routable, R: Routable,
Q: Clone + PartialEq + Serialize, Q: Clone + PartialEq + Serialize,
S: Clone + PartialEq,
{ {
/// CSS classes to add to the anchor element (optional). /// CSS classes to add to the anchor element (optional).
#[prop_or_default] #[prop_or_default]
@ -22,6 +23,9 @@ where
/// Route query data /// Route query data
#[prop_or_default] #[prop_or_default]
pub query: Option<Q>, pub query: Option<Q>,
/// Route state data
#[prop_or_default]
pub state: Option<S>,
#[prop_or_default] #[prop_or_default]
pub disabled: bool, pub disabled: bool,
/// [`NodeRef`](yew::html::NodeRef) for the `<a>` element. /// [`NodeRef`](yew::html::NodeRef) for the `<a>` element.
@ -33,18 +37,20 @@ where
/// A wrapper around `<a>` tag to be used with [`Router`](crate::Router) /// A wrapper around `<a>` tag to be used with [`Router`](crate::Router)
#[function_component] #[function_component]
pub fn Link<R, Q = ()>(props: &LinkProps<R, Q>) -> Html pub fn Link<R, Q = (), S = ()>(props: &LinkProps<R, Q, S>) -> Html
where where
R: Routable + 'static, R: Routable + 'static,
Q: Clone + PartialEq + Serialize + 'static, Q: Clone + PartialEq + Serialize + 'static,
S: Clone + PartialEq + 'static,
{ {
let LinkProps { let LinkProps {
classes, classes,
to, to,
children,
disabled,
query, query,
state,
disabled,
anchor_ref, anchor_ref,
children,
} = props.clone(); } = props.clone();
let navigator = use_navigator().expect_throw("failed to get navigator"); let navigator = use_navigator().expect_throw("failed to get navigator");
@ -53,21 +59,30 @@ where
let navigator = navigator.clone(); let navigator = navigator.clone();
let to = to.clone(); let to = to.clone();
let query = query.clone(); let query = query.clone();
let state = state.clone();
Callback::from(move |e: MouseEvent| { Callback::from(move |e: MouseEvent| {
if e.meta_key() || e.ctrl_key() || e.shift_key() || e.alt_key() { if e.meta_key() || e.ctrl_key() || e.shift_key() || e.alt_key() {
return; return;
} }
e.prevent_default(); e.prevent_default();
match query { match (&state, &query) {
None => { (None, None) => {
navigator.push(&to); navigator.push(&to);
} }
Some(ref data) => { (Some(state), None) => {
navigator.push_with_state(&to, state.clone());
}
(None, Some(query)) => {
navigator navigator
.push_with_query(&to, data) .push_with_query(&to, query)
.expect_throw("failed push history with query"); .expect_throw("failed push history with query");
} }
(Some(state), Some(query)) => {
navigator
.push_with_query_and_state(&to, query, state.clone())
.expect_throw("failed push history with query and state");
}
} }
}) })
}; };