throttle history updates to 100ms

This commit is contained in:
Evan Almloff 2023-06-19 12:04:06 -05:00
parent fe626c67bd
commit bc063c58b7
3 changed files with 116 additions and 4 deletions

View file

@ -14,6 +14,18 @@ pub struct RouterConfigFactory<R: Routable> {
config: RefCell<Option<Box<dyn FnOnce() -> RouterConfig<R>>>>,
}
#[cfg(feature = "serde")]
impl<R: Routable> Default for RouterConfigFactory<R>
where
<R as FromStr>::Err: std::fmt::Display,
R: serde::Serialize + serde::de::DeserializeOwned,
{
fn default() -> Self {
Self::from(RouterConfig::default)
}
}
#[cfg(not(feature = "serde"))]
impl<R: Routable> Default for RouterConfigFactory<R>
where
<R as FromStr>::Err: std::fmt::Display,
@ -31,6 +43,19 @@ impl<R: Routable, F: FnOnce() -> RouterConfig<R> + 'static> From<F> for RouterCo
}
}
#[cfg(feature = "serde")]
/// The props for [`GenericRouter`].
#[derive(Props)]
pub struct GenericRouterProps<R: Routable>
where
<R as FromStr>::Err: std::fmt::Display,
R: serde::Serialize + serde::de::DeserializeOwned,
{
#[props(default, into)]
config: RouterConfigFactory<R>,
}
#[cfg(not(feature = "serde"))]
/// The props for [`GenericRouter`].
#[derive(Props)]
pub struct GenericRouterProps<R: Routable>
@ -41,6 +66,7 @@ where
config: RouterConfigFactory<R>,
}
#[cfg(not(feature = "serde"))]
impl<R: Routable> PartialEq for GenericRouterProps<R>
where
<R as FromStr>::Err: std::fmt::Display,
@ -51,6 +77,19 @@ where
}
}
#[cfg(feature = "serde")]
impl<R: Routable> PartialEq for GenericRouterProps<R>
where
<R as FromStr>::Err: std::fmt::Display,
R: serde::Serialize + serde::de::DeserializeOwned,
{
fn eq(&self, _: &Self) -> bool {
// prevent the router from re-rendering when the initial url or config changes
true
}
}
#[cfg(not(feature = "serde"))]
/// A component that renders the current route.
pub fn GenericRouter<R: Routable + Clone>(cx: Scope<GenericRouterProps<R>>) -> Element
where
@ -79,3 +118,34 @@ where
GenericOutlet::<R> {}
}
}
#[cfg(feature = "serde")]
/// A component that renders the current route.
pub fn GenericRouter<R: Routable + Clone>(cx: Scope<GenericRouterProps<R>>) -> Element
where
<R as FromStr>::Err: std::fmt::Display,
R: serde::Serialize + serde::de::DeserializeOwned,
{
use_context_provider(cx, || {
#[allow(unreachable_code, unused_variables)]
if let Some(outer) = cx.consume_context::<GenericRouterContext<R>>() {
let msg = "Router components should not be nested within each other";
error!("{msg}, inner will be inactive and transparent");
#[cfg(debug_assertions)]
panic!("{}", msg);
}
let router = GenericRouterContext::new(
(cx.props
.config
.config
.take()
.expect("use_context_provider ran twice"))(),
cx.schedule_update_any(),
);
router
});
render! {
GenericOutlet::<R> {}
}
}

View file

@ -104,8 +104,18 @@ impl<R: Routable> WebHistory<R> {
let myself = Self::new_inner(
prefix,
do_scroll_restoration,
EventListener::new(&document, "scroll", move |_| {
update_scroll::<R>(&w, &h);
EventListener::new(&document, "scroll", {
let mut last_updated = 0.0;
move |evt| {
// the time stamp in milliseconds
let time_stamp = evt.time_stamp();
// throttle the scroll event to 100ms
if (time_stamp - last_updated) < 100.0 {
return;
}
update_scroll::<R>(&w, &h);
last_updated = time_stamp;
}
}),
);
@ -134,8 +144,18 @@ impl<R: Routable> WebHistory<R> {
let myself = Self::new_inner(
prefix,
do_scroll_restoration,
EventListener::new(&document, "scroll", move |_| {
update_scroll::<R>(&w, &h);
EventListener::new(&document, "scroll", {
let mut last_updated = 0.0;
move |evt| {
// the time stamp in milliseconds
let time_stamp = evt.time_stamp();
// throttle the scroll event to 100ms
if (time_stamp - last_updated) < 100.0 {
return;
}
update_scroll::<R>(&w, &h);
last_updated = time_stamp;
}
}),
);

View file

@ -30,6 +30,28 @@ pub struct RouterConfig<R: Routable> {
pub(crate) on_update: Option<RoutingCallback<R>>,
}
#[cfg(feature = "serde")]
impl<R: Routable + Clone> Default for RouterConfig<R>
where
<R as std::str::FromStr>::Err: std::fmt::Display,
R: serde::Serialize + serde::de::DeserializeOwned,
{
fn default() -> Self {
Self {
failure_external_navigation: FailureExternalNavigation::<R>,
history: {
#[cfg(all(target_arch = "wasm32", feature = "web"))]
let history = Box::<WebHistory<R>>::default();
#[cfg(not(all(target_arch = "wasm32", feature = "web")))]
let history = Box::<MemoryHistory<R>>::default();
history
},
on_update: None,
}
}
}
#[cfg(not(feature = "serde"))]
impl<R: Routable + Clone> Default for RouterConfig<R>
where
<R as std::str::FromStr>::Err: std::fmt::Display,