Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

made show fallback optional #1817

Merged
merged 3 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions leptos/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,12 @@ pub use wasm_bindgen; // used in islands
feature = "template_macro"
))]
pub use web_sys; // used in islands

mod children;
mod view_fn;
pub use children::*;
pub use view_fn::*;

extern crate self as leptos;

/// A type for taking anything that implements [`IntoAttribute`].
Expand Down
18 changes: 7 additions & 11 deletions leptos/src/show.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
use leptos::{component, ChildrenFn};
use leptos::{component, ChildrenFn, ViewFn};
use leptos_dom::IntoView;
use leptos_reactive::{create_memo, signal_prelude::*};

/// A component that will show its children when the `when` condition is `true`,
/// and show the fallback when it is `false`, without rerendering every time
/// the condition changes.
///
/// *Note*: Because of the nature of generic arguments, it’s not really possible
/// to make the `fallback` optional. If you want an empty fallback state—in other
/// words, if you want to show the children if `when` is true and noting otherwise—use
/// `fallback=|_| ()` (i.e., a fallback function that returns the unit type `()`).
/// The fallback prop is optional and defaults to rendering nothing.
///
/// ```rust
/// # use leptos_reactive::*;
Expand All @@ -34,23 +31,22 @@ use leptos_reactive::{create_memo, signal_prelude::*};
tracing::instrument(level = "info", skip_all)
)]
#[component]
pub fn Show<F, W, IV>(
pub fn Show<W>(
/// The children will be shown whenever the condition in the `when` closure returns `true`.
children: ChildrenFn,
/// A closure that returns a bool that determines whether this thing runs
when: W,
/// A closure that returns what gets rendered if the when statement is false
fallback: F,
/// A closure that returns what gets rendered if the when statement is false. By default this is the empty view.
#[prop(optional, into)]
fallback: ViewFn,
) -> impl IntoView
where
W: Fn() -> bool + 'static,
F: Fn() -> IV + 'static,
IV: IntoView,
{
let memoized_when = create_memo(move |_| when());

move || match memoized_when.get() {
true => children().into_view(),
false => fallback().into_view(),
false => fallback.run(),
}
}
12 changes: 6 additions & 6 deletions leptos/src/suspense_component.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use leptos::ViewFn;
use leptos_dom::{DynChild, HydrationCtx, IntoView};
use leptos_macro::component;
#[cfg(any(feature = "csr", feature = "hydrate"))]
Expand Down Expand Up @@ -57,15 +58,14 @@ use std::rc::Rc;
tracing::instrument(level = "info", skip_all)
)]
#[component]
pub fn Suspense<F, E, V>(
/// Returns a fallback UI that will be shown while `async` [`Resource`](leptos_reactive::Resource)s are still loading.
fallback: F,
pub fn Suspense<V>(
/// Returns a fallback UI that will be shown while `async` [`Resource`](leptos_reactive::Resource)s are still loading. By default this is the empty view.
#[prop(optional, into)]
fallback: ViewFn,
/// Children will be displayed once all `async` [`Resource`](leptos_reactive::Resource)s have resolved.
children: Rc<dyn Fn() -> V>,
) -> impl IntoView
where
F: Fn() -> E + 'static,
E: IntoView,
V: IntoView + 'static,
{
let orig_children = children;
Expand All @@ -89,7 +89,7 @@ where
let fallback = create_memo({
move |_| {
provide_context(context);
fallback().into_view()
fallback.run()
}
});

Expand Down
18 changes: 8 additions & 10 deletions leptos/src/transition.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use leptos::ViewFn;
use leptos_dom::{Fragment, HydrationCtx, IntoView, View};
use leptos_macro::component;
use leptos_reactive::{
Expand Down Expand Up @@ -66,21 +67,18 @@ use std::{
tracing::instrument(level = "info", skip_all)
)]
#[component(transparent)]
pub fn Transition<F, E>(
/// Will be displayed while resources are pending.
fallback: F,
pub fn Transition(
/// Will be displayed while resources are pending. By default this is the empty view.
#[prop(optional, into)]
fallback: ViewFn,
/// A function that will be called when the component transitions into or out of
/// the `pending` state, with its argument indicating whether it is pending (`true`)
/// or not pending (`false`).
#[prop(optional, into)]
set_pending: Option<SignalSetter<bool>>,
/// Will be displayed once all resources have resolved.
children: Box<dyn Fn() -> Fragment>,
) -> impl IntoView
where
F: Fn() -> E + 'static,
E: IntoView,
{
) -> impl IntoView {
let prev_children = Rc::new(RefCell::new(None::<View>));

let first_run = create_rw_signal(true);
Expand All @@ -105,12 +103,12 @@ where

if let Some(prev_children) = &*prev_child.borrow() {
if is_first_run || was_first_run {
fallback().into_view()
fallback.run()
} else {
prev_children.clone()
}
} else {
fallback().into_view()
fallback.run()
}
}
})
Expand Down
30 changes: 30 additions & 0 deletions leptos/src/view_fn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use leptos_dom::{IntoView, View};
use std::rc::Rc;

/// New-type wrapper for the a function that returns a view with `From` and `Default` traits implemented
/// to enable optional props in for example `<Show>` and `<Suspense>`.
#[derive(Clone)]
pub struct ViewFn(Rc<dyn Fn() -> View>);

impl Default for ViewFn {
fn default() -> Self {
Self(Rc::new(|| ().into_view()))
}
}

impl<F, IV> From<F> for ViewFn
where
F: Fn() -> IV + 'static,
IV: IntoView,
{
fn from(value: F) -> Self {
Self(Rc::new(move || value().into_view()))
}
}

impl ViewFn {
/// Execute the wrapped function
pub fn run(&self) -> View {
(self.0)()
}
}
Loading