Created
October 14, 2021 07:55
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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