Skip to content

Instantly share code, notes, and snippets.

@arctic-hen7
Created October 14, 2021 07:55
Show Gist options
  • Save arctic-hen7/19f49aaf3cad2d33b605814f5ba42409 to your computer and use it in GitHub Desktop.
Save arctic-hen7/19f49aaf3cad2d33b605814f5ba42409 to your computer and use it in GitHub Desktop.
A workaround for Sycamore #276. This is adapted from https://github.com/danielalvsaaker/sycamore-mre/blob/reactive/src/main.rs.
// All our changes occur here
#[component(App<G>)]
fn app() -> Template<G> {
let root_ref = NodeRef::new();
template! {
// The router will use `root_ref`, so it needs to be `move` to avoid lifetime errors
Router(RouterProps::new(HistoryIntegration::new(), /* NEW START */ move /* NEW END */ |route: StateHandle<Routes>| {
// Template interpolation is the problem, so we get rid of it
// let template = Signal::new(Template::empty()); // OLD
// We're not using template interpolation anymore, so we want to clone `root_ref` in instead of `template`
// create_effect(cloned!((template) => move || { // OLD
create_effect(cloned!((root_ref) => move || { // NEW
let route = route.get();
// We're not using template interpolation anymore, so we want to clone `root_ref` in instead of `template`
// spawn_local(cloned!((template) => async move { //OLD
spawn_local(cloned!((root_ref) => async move { //NEW
// Note: we've moved our route `match` statement from here into the `render_to` we've added later on
// We're not using template interpolation anymore, so we don't need this
// template.set(t); // OLD
// NEW START
// Turn our reference to a Sycamore node into a `web_sys` DOM element
// We can't do this straight away because it needs to have time to render (so we do it in a future)
let root = root_ref.get::<DomNode>().unchecked_into::<web_sys::Element>();
// Now get rid of everything in that `div`
// If we don't do this, each page is just rendered on top of the last one
root.set_inner_html("");
// And now render our new template to that `div`
sycamore::render_to(
// This `match` used to be further up, but we need to put it here now (otherwise we get reactive scope errors)
|| match route.as_ref() {
Routes::Index => template! {
h1() { "Index" }
},
Routes::Page => template! {
h1() { "Page" }
Page() // Or whatever template you want to render here with `bind:value`
},
Routes::OtherPage => template! {
h1() { "Other page" }
},
_ => template! {
h1() { "Not found" }
},
},
&root
);
// NEW END
}));
}));
template! {
div() {
div() {
a(href="/") { "Index" }
br()
a(href="/page") { "Page" }
br()
a(href="/other_page") { "Other page" }
}
// We replace the template interpolation with a DOM node that we can render to
// (template.get().as_ref().clone()) // OLD
div(ref = root_ref) // NEW
}
}
}))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment