-
-
Notifications
You must be signed in to change notification settings - Fork 428
Suggestion: a main app component #157
Comments
It might be a little tricky because of I've wondered about having some way to preserve components between route transitions: <Nav key:nav/> <!-- because of key:nav, the component is 'recycled', never destroyed --> Having a main app component would solve that problem in a slightly more elegant way, but I think we'd need to solve the async loading problem before we could really do that. (Perhaps we need to steal some of these ideas from React.) I agree that there should be a way to listen for route changes. |
In my app, I also preload route data. What I do is I guess what I proposed here is not changing the way (ps. thanks for the link! I'll check it out) |
Ah, I think I understand what you mean now. Yes, that could potentially work. Will think on that. Definitely needs spread in order to be ergonomic. |
Something like this would be great. Currently this is a blocker for us using Sapper for a work project. We need nested routes where components are preserved between routes. For example one section of the app has a Google map and an overlay component that controls the route and updates the map's state, currently if we used Sapper each route change would teardown and refresh the map. |
I think for Sapper we need something like Nuxt.js and Next.js. We need a |
I think it would be simpler to use dynamic components — to update the original example to v2 syntax, and throw in some layout: <Nav {route}/>
<svelte:component this={Page} {query} {params}/>
<footer>
<p>this appears on every page</p>
</footer> The act of navigation, as far as the client-side router goes, would look something like this (pseudo-code): const route = selectRoute(window.location);
const { Page } = route;
if (Page.preload) {
await Page.preload.call(preloadContext, {
query: route.query,
params: route.params
});
}
if (redirected || erroredInPreload) handleThatShit();
app.set({
route: new Route(route), // wrapper that provides convenience methods like 'matches', maybe
Page,
query: route.query,
params: route.params
}); We could extend that idea and solve a common problem declaratively (e.g. #248): +{#if preloading}
+ <FakeProgressBar/>
+{/if}
<Nav {route}/>
<svelte:component this={Page} {query} {params}/>
<footer>
<p>this appears on every page</p>
</footer> if (Page.preload) {
+ app.set({ preloading: true });
await Page.preload.call(preloadContext, {
query: route.query,
params: route.params
});
}
// ...
app.set({
+ preloading: false
route: new Route(route), // wrapper that provides convenience methods like 'matches', maybe
Page,
query: route.query,
params: route.params
}); It might turn out we don't actually need hooks, and can just use the familiar Bikeshedding time: what do we call this new app component? |
Oh, and if a |
That could possibly work. We could call the new component |
I suppose in the spirit of 'less magic', you could make it explicit, so that it doesn't really matter what you call it and import { init } from 'sapper/runtime.js';
import { routes } from './manifest/client.js';
import Layout from './Layout.html';
init({
target: document.querySelector('#sapper')
routes,
component: Layout
}); |
Awesome, if we could have it working by morning (Sydney time) that'll be grand. 😇 Jokes aside, this sounds promising. Would this technique work for deeply nested pages? |
@rob-balfre I think all nested components would be destroyed on route change. I think only the Layout component would remain. @Rich-Harris yeah I like the idea of making it less magic-y. Explicit always better than implicit in most cases. |
@rob-balfre maybe morning Sydney time on Monday? (I actually think this should be relatively straightforward to implement, and I'm impatient, so gonna try and do it over the weekend.) What do you mean by deeply nested pages exactly? @silentworks is right that only the Layout component would remain... though I've been thinking about this issue a little. Right now, the way transitions work is that if you create a component, its intros will run, but if you destroy it then outros don't run — they're destroyed immediately. That makes it tricky, if not impossible, to achieve many transition effects. As a starting point, it would be useful if it were possible to outro components, and in fact there's an issue for it: sveltejs/svelte#1211. I think I have an idea of how to solve it. That wouldn't help if you had a single <svelte:component switch:outin this={Page} {query} {params}/> ( Essentially I want it to be dead simple to do this sort of thing, and this feels like a first step towards that. Also, one more thought I had: if we had a value that indicated not just the |
@Rich-Harris the last part of your message is the reason why I think having I am not too sure about adding an directive on the |
@Rich-Harris here is an example of how Vue is working this with its https://vuejs.org/v2/guide/transitions.html#Transitioning-Between-Components |
@Rich-Harris 🥇Monday is a deal! I'll buy you a coffee/beer if you ever come to Sydney! By deeply nested I mean anything more than just one level deep. A basic example: |
@rob-balfre Ah, gotcha. Kind of. If you had a page like So if that page looked like this... <TopLevelNav active={params.menu}/>
{#if params.menu === 'home'}
<Home {params}/>
{:else if params.menu === 'profile'}
<Profile {params}/>
{:else if params.menu === 'settings'}
<Settings {params}/>
{/if} ...then navigating would basically just change the value of More likely, you'd have something like Hope that made sense. |
Ok, here's a brainteaser. What should the default scroll behaviour be when navigating to the 'same page' but with different |
I would scroll to the top even on the same page with same params, since that's the default browser behavior when clicking plain-old links. Just think about what you'd expect when clicking links in a site's footer. Would |
Have opened a PR, if anyone is curious: #259 |
@mrkishi yeah, I came to the same conclusion. It also happens to be the option that doesn't require any extra work :) |
switch to single App component model
This is released in 0.12. Migration guide here. Thanks everyone! |
@Rich-Harris brilliant, thanks so much. |
Would someone be able to add a working example of this somewhere? in the Svelte REPL maybe? but then where do we define the outin switch behaviour? Just read through the sveltejs Gitter and it seems you're already aware of the page-transitions example, so that's cool |
So, I've been using pure Svelte and Roadtrip in order to build an app with an architecture similar to sapper. I wanted to use sapper but it was just too early... Thankfully this allowed me to test different things that might benefit sapper.
One of them is having a main app component. The simplest (and implicitly used if one's not provided) main app component would be something like this:
The framework would then define an API for the main app component in order to expose the routed components (although the minimal API would be simply "there's a
routeComponent
component and arouteData
object").This would allow us to have persistent components throughout the whole app lifecycle. It would also be a good place to expand sapper's routing API (which is something I think is currently lacking -- say, getting notified whenever routes change), with full Svelte access.
This would probably only be ergonomic once spread parameters are in, but hopefully it's worth tinkering with!
Thoughts?
The text was updated successfully, but these errors were encountered: