framesurge / perseus

A state-driven web development framework for Rust with full support for server-side rendering and static generation.
https://framesurge.sh/perseus/en-US
MIT License
2.18k stars 89 forks source link

[Router] [Bug] When using `.incremental_generation()`, you cannot navigate to a new route on the same page. #283

Closed dessalines closed 1 year ago

dessalines commented 1 year ago

This issue is reporting a bug in the code of Perseus. Details of the scope will be available in issue labels. The author described their issue as follows:

[Router] [Bug] When using .incremental_generation(), you cannot navigate to a new route on the same page.

The steps to reproduce this issue are as follows:

I have an app with a search input in the navbar. I'd like to be able to perform another search, even while on the /search/some_query route.

Because of this, things like paging (IE moving from /posts/page/1 to /posts/page/2) are currently impossible.

I've tried using rel = external, but that also didn't fix the issue.

A minimum reproducible example is available at <I can create this if necessary, just let me know.>.

Tribble internal data dHJpYmJsZS1yZXBvcnRlZCxDLWJ1ZyxhdXRob3Itd2lsbGluZy10by1pbXBs
Miroito commented 1 year ago

I tried to reproduce your issue but the code below is working as expected (clicking on the links gets you to the right page including the state). What else are you trying to do that eventually breaks?

use perseus::prelude::*;
use serde::{Deserialize, Serialize};
use sycamore::prelude::*;

fn posts_page<G: Html>(cx: Scope, state: PageState) -> View<G> {
    view! { cx,
        p () {
            "You're on the page for post "
            (state.post_n)
        }
        a (style="display: block", href="posts/1") { "post 1" }
        a (style="display: block", href="posts/2") { "post 2" }
        a (style="display: block", href="posts/3") { "post 3" }
        a (style="display: block", href="posts/4") { "post 4" }
        a (style="display: block", href="posts/5") { "post 5" }
    }
}

#[derive(Serialize, Deserialize, Clone, UnreactiveState)]
struct PageState {
    post_n: String,
}

pub fn get_template<G: Html>() -> Template<G> {
    Template::build("posts")
        .view_with_unreactive_state(posts_page)
        .build_state_fn(get_build_state)
        .incremental_generation()
        .build_paths_fn(get_build_paths)
        .build()
}

#[engine_only_fn]
async fn get_build_state(
    info: StateGeneratorInfo<()>,
) -> Result<PageState, BlamedError<std::io::Error>> {
    Ok(PageState { post_n: info.path })
}

#[engine_only_fn]
async fn get_build_paths() -> BuildPaths {
    BuildPaths {
        paths: vec!["".to_string()],
        extra: ().into(),
    }
}
dessalines commented 1 year ago

I sincerely apologize yet again, I tried to reproduce this and couldn't.

I think the issues I was having before, having to do with deserializing numbers, which produced state errors, also broke routing. Once those were fixed, it also fixed this.

Sorry again for wasting your time @Miroito .

Miroito commented 1 year ago

@dessalines Everything is fine, we're all learning. Good luck on your Perseus journey!