Skip to content

Commit 6252f6a

Browse files
committed
refactor: simplified error router states
BREAKING CHANGE: removed `RouterLoadState::ErrorLoaded` entirely (you should now rely solely on error views, which will be able to poll the last router state, which probably contributed to/caused the error)
1 parent f5f4dca commit 6252f6a

File tree

7 files changed

+34
-27
lines changed

7 files changed

+34
-27
lines changed

examples/core/router_state/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9-
perseus = { path = "../../../packages/perseus", features = [ "hydrate" ] }
9+
# TODO This doesn't work with hydration for some reason...
10+
perseus = { path = "../../../packages/perseus", features = [ ] }
1011
sycamore = "^0.8.1"
1112
serde = { version = "1", features = ["derive"] }
1213
serde_json = "1"

examples/core/router_state/src/templates/index.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,15 @@ fn router_state_page<G: Html>(cx: Scope) -> View<G> {
2727
path,
2828
} => format!("Loading {} (template: {}).", *path, template_name),
2929
RouterLoadState::Server => "We're on the server.".to_string(),
30-
// Since this code is running in a page, it's a little pointless to handle an error
31-
// page, which would replace this page (we wouldn't be able to
32-
// display anything if this happened)
33-
RouterLoadState::ErrorLoaded { .. } => unreachable!(),
3430
};
3531
load_state_str.set(new_str);
3632
});
3733
}
3834

3935
view! { cx,
40-
a(href = "about", id = "about-link") { "About!" }
41-
4236
p { (load_state_str.get()) }
37+
38+
a(href = "about", id = "about-link") { "About!" }
4339
}
4440
}
4541

packages/perseus/src/reactor/initial_load.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ impl<G: Html> Reactor<G> {
2323
/// Gets the initial view to hydrate, which will be the same as what the
2424
/// engine-side rendered and provided. This will automatically extract
2525
/// the current path from the browser.
26+
///
27+
/// This will set the router state to `Loaded` if it succeeds.
2628
pub(crate) fn get_initial_view<'a>(
2729
&self,
2830
cx: Scope<'a>,
@@ -128,7 +130,14 @@ impl<G: Html> Reactor<G> {
128130

129131
// Render the actual template to the root (done imperatively due to child
130132
// scopes)
131-
let (view, disposer) = entity.render_for_template_client(full_path, state, cx)?;
133+
let (view, disposer) =
134+
entity.render_for_template_client(full_path.clone(), state, cx)?;
135+
136+
// Update the router state
137+
self.router_state.set_load_state(RouterLoadState::Loaded {
138+
template_name: entity.get_path(),
139+
path: full_path,
140+
});
132141

133142
Ok(InitialView::View(view, disposer))
134143
}

packages/perseus/src/reactor/start.rs

+1
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ impl Reactor<BrowserNodeType> {
237237
page_disposer.update(disposer);
238238
}
239239

240+
// Note that the router state has already been correctly set to `Loaded`
240241
(view, false)
241242
}
242243
// On a redirect, return a view that just redirects straight away (of course,

packages/perseus/src/reactor/state.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@ impl<G: Html> Freeze for Reactor<G> {
3030
// It would be impressive to manage this timing, but it's fine to go to the route we
3131
// were in the middle of loading when we thaw
3232
RouterLoadState::Loading { path, .. } => Some(path.clone()),
33-
// If we encounter this during re-hydration, we won't try to set the URL in the
34-
// browser
35-
RouterLoadState::ErrorLoaded { .. } => None,
3633
RouterLoadState::Server => None,
34+
// Error states are no longer propagated to the router, so we will attempt
35+
// to pick up the last successful load implicitly
3736
},
3837
state_store: self.state_store.freeze_to_hash_map(),
3938
};
@@ -86,9 +85,9 @@ impl<G: Html> Reactor<G> {
8685
if let Some(frozen_route) = route {
8786
let curr_route = match &*self.router_state.get_load_state_rc().get_untracked() {
8887
// If we've loaded a page, or we're about to, only change the route if necessary
89-
RouterLoadState::Loaded { path, .. }
90-
| RouterLoadState::Loading { path, .. }
91-
| RouterLoadState::ErrorLoaded { path } => path.clone(),
88+
RouterLoadState::Loaded { path, .. } | RouterLoadState::Loading { path, .. } => {
89+
path.clone()
90+
}
9291
// Since this function is only defined on the browser-side, this should
9392
// be completely impossible (note that the user can't change the router
9493
// state manually)

packages/perseus/src/reactor/subsequent_load.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -151,19 +151,20 @@ impl<G: Html> Reactor<G> {
151151
.await?;
152152

153153
let template_name = entity.get_path();
154+
// Now return the view that should be rendered
155+
let (view, disposer) = entity.render_for_template_client(
156+
full_path.clone(),
157+
TemplateState::from_value(page_data.state),
158+
cx,
159+
)?;
160+
154161
// Pre-emptively update the router state
155162
checkpoint("page_interactive");
156163
// Update the router state
157164
self.router_state.set_load_state(RouterLoadState::Loaded {
158165
template_name,
159-
path: full_path.clone(),
166+
path: full_path,
160167
});
161-
// Now return the view that should be rendered
162-
let (view, disposer) = entity.render_for_template_client(
163-
full_path,
164-
TemplateState::from_value(page_data.state),
165-
cx,
166-
)?;
167168

168169
Ok((view, disposer))
169170
}

packages/perseus/src/router/router_state.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ impl RouterState {
100100
/// The current load state of the router. You can use this to be warned of when
101101
/// a new page is about to be loaded (and display a loading bar or the like,
102102
/// perhaps).
103+
///
104+
/// In the event of an error, the router state will be left untouched (allowing
105+
/// it to be inspected in error views with reactor access to determine what the
106+
/// last page was, and therefore where the error likely occurred; usually, the
107+
/// last page will be in a `Loading` state). Popup errors will not cause any
108+
/// change to this state.
103109
#[derive(Clone, Debug)]
104110
pub enum RouterLoadState {
105111
/// The page has been loaded.
@@ -110,12 +116,6 @@ pub enum RouterLoadState {
110116
/// we're using i18n).
111117
path: PathMaybeWithLocale,
112118
},
113-
/// An error page has been loaded. Note that this will not account for any
114-
/// popup errors.
115-
ErrorLoaded {
116-
/// The path of this error.
117-
path: PathMaybeWithLocale,
118-
},
119119
/// A new page is being loaded, and will soon replace whatever is currently
120120
/// loaded. The name of the new template is attached.
121121
Loading {

0 commit comments

Comments
 (0)