mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
parent
45275ff8d4
commit
4034aa9c11
7 changed files with 77 additions and 2 deletions
|
@ -1,4 +1,4 @@
|
|||
use leptos::{component, Scope, IntoView, view};
|
||||
use leptos::{component, view, IntoView, Scope};
|
||||
use leptos_router::*;
|
||||
|
||||
#[component]
|
||||
|
@ -6,7 +6,7 @@ pub fn Nav(cx: Scope) -> impl IntoView {
|
|||
view! { cx,
|
||||
<header class="header">
|
||||
<nav class="inner">
|
||||
<A href="/">
|
||||
<A href="/home">
|
||||
<strong>"HN"</strong>
|
||||
</A>
|
||||
<A href="/new">
|
||||
|
|
|
@ -20,6 +20,7 @@ pub fn RouterExample(cx: Scope) -> impl IntoView {
|
|||
<A exact=true href="/">"Contacts"</A>
|
||||
<A href="about">"About"</A>
|
||||
<A href="settings">"Settings"</A>
|
||||
<A href="redirect-home">"Redirect to Home"</A>
|
||||
</nav>
|
||||
<main>
|
||||
<Routes>
|
||||
|
@ -44,6 +45,10 @@ pub fn RouterExample(cx: Scope) -> impl IntoView {
|
|||
path="settings"
|
||||
view=move |cx| view! { cx, <Settings/> }
|
||||
/>
|
||||
<Route
|
||||
path="redirect-home"
|
||||
view=move |cx| view! { cx, <Redirect path="/"/> }
|
||||
/>
|
||||
</Routes>
|
||||
</main>
|
||||
</Router>
|
||||
|
|
|
@ -438,6 +438,7 @@ fn provide_contexts(cx: leptos::Scope, req: &HttpRequest, res_options: ResponseO
|
|||
provide_context(cx, MetaContext::new());
|
||||
provide_context(cx, res_options);
|
||||
provide_context(cx, req.clone());
|
||||
provide_server_redirect(cx, move |path| redirect(cx, path));
|
||||
}
|
||||
|
||||
fn leptos_corrected_path(req: &HttpRequest) -> String {
|
||||
|
|
|
@ -447,6 +447,7 @@ where
|
|||
provide_context(cx, MetaContext::new());
|
||||
provide_context(cx, req_parts);
|
||||
provide_context(cx, default_res_options);
|
||||
provide_server_redirect(cx, move |path| redirect(cx, path));
|
||||
app_fn(cx).into_view(cx)
|
||||
}
|
||||
};
|
||||
|
|
|
@ -22,6 +22,7 @@ percent-encoding = "2"
|
|||
thiserror = "1"
|
||||
serde_urlencoded = "0.7"
|
||||
serde = "1"
|
||||
tracing = "0.1"
|
||||
js-sys = { version = "0.3" }
|
||||
wasm-bindgen = { version = "0.2" }
|
||||
wasm-bindgen-futures = { version = "0.4" }
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
mod form;
|
||||
mod link;
|
||||
mod outlet;
|
||||
mod redirect;
|
||||
mod route;
|
||||
mod router;
|
||||
mod routes;
|
||||
|
@ -8,6 +9,7 @@ mod routes;
|
|||
pub use form::*;
|
||||
pub use link::*;
|
||||
pub use outlet::*;
|
||||
pub use redirect::*;
|
||||
pub use route::*;
|
||||
pub use router::*;
|
||||
pub use routes::*;
|
||||
|
|
65
router/src/components/redirect.rs
Normal file
65
router/src/components/redirect.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use crate::{use_navigate, use_resolved_path, NavigateOptions};
|
||||
use leptos::{component, provide_context, use_context, IntoView, Scope};
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Redirects the user to a new URL, whether on the client side or on the server
|
||||
/// side. If rendered on the server, this sets a `302` status code and sets a `Location`
|
||||
/// header. If rendered in the browser, it uses client-side navigation to redirect.
|
||||
/// In either case, it resolves the route relative to the current route. (To use
|
||||
/// an absolute path, prefix it with `/`).
|
||||
///
|
||||
/// **Note**: Support for server-side redirects is provided by the server framework
|
||||
/// integrations (`leptos_actix` and `leptos_axum`). If you’re not using one of those
|
||||
/// integrations, you should manually provide a way of redirecting on the server
|
||||
/// using [provide_server_redirect].
|
||||
#[component]
|
||||
pub fn Redirect<P>(
|
||||
cx: Scope,
|
||||
/// The relative path to which the user should be redirected.
|
||||
path: P,
|
||||
/// Navigation options to be used on the client side.
|
||||
#[prop(optional)]
|
||||
options: Option<NavigateOptions>,
|
||||
) -> impl IntoView
|
||||
where
|
||||
P: std::fmt::Display + 'static,
|
||||
{
|
||||
// resolve relative path
|
||||
let path = use_resolved_path(cx, move || path.to_string());
|
||||
let path = path.get().unwrap_or_else(|| "/".to_string());
|
||||
|
||||
// redirect on the server
|
||||
if let Some(redirect_fn) = use_context::<ServerRedirectFunction>(cx) {
|
||||
(redirect_fn.f)(&path);
|
||||
}
|
||||
|
||||
// redirect on the client
|
||||
let navigate = use_navigate(cx);
|
||||
navigate(&path, options.unwrap_or_default())
|
||||
}
|
||||
|
||||
/// Wrapping type for a function provided as context to allow for
|
||||
/// server-side redirects. See [provide_server_redirect]
|
||||
/// and [Redirect].
|
||||
#[derive(Clone)]
|
||||
pub struct ServerRedirectFunction {
|
||||
f: Rc<dyn Fn(&str)>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ServerRedirectFunction {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("ServerRedirectFunction").finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides a function that can be used to redirect the user to another
|
||||
/// absolute path, on the server. This should set a `302` status code and an
|
||||
/// appropriate `Location` header.
|
||||
pub fn provide_server_redirect(cx: Scope, handler: impl Fn(&str) + 'static) {
|
||||
provide_context(
|
||||
cx,
|
||||
ServerRedirectFunction {
|
||||
f: Rc::new(handler),
|
||||
},
|
||||
)
|
||||
}
|
Loading…
Reference in a new issue