Coder Social home page Coder Social logo

Fragment route not working about yew_router HOT 15 CLOSED

jetli avatar jetli commented on May 26, 2024
Fragment route not working

from yew_router.

Comments (15)

hgzimmerman avatar hgzimmerman commented on May 26, 2024

As an initial fix, could you try using "{*}#/login" and a dummy (String) tuple on your variants. That has the semantic meaning of: match anything until a "#/login" is encountered. Its not ideal though because you need to add a useless String to be captured for every variant.

Which gives me this idea which may be worth trying out:

#[derive(Switch, Debug, Clone)]
#[to="{*:_path}#{*:app_route}"] // everything up to # goes to _path, everything after will make up app_route
pub struct FullRoute {
    _path: String,
    app_route: AppRoute
}

#[derive(Switch, Debug, Clone)]
pub enum AppRoute {
    #[to = "/login"]
    Login,
    #[to = "/"]
    Home,
}

And then just match within the Router component using the inner AppRoute.

Note, fragment routing isn't a stated design goal of this library, but I do want to support it where possible, however ugly it may be, as long as it doesn't impact the usability of the typical routing scheme.

from yew_router.

hgzimmerman avatar hgzimmerman commented on May 26, 2024

Provided the above solution works, I should either create an example, or otherwise demonstrate this as the accepted way of using hash routing in cases with leading url paths.

from yew_router.

jetli avatar jetli commented on May 26, 2024

#[to="{*:_path}#{*:app_route}"] seems not support #

proc-macro derive panicked
message: `"*:app_route"` is not a valid identifier

from yew_router.

hgzimmerman avatar hgzimmerman commented on May 26, 2024

Hmm, I'll investigate this then.

from yew_router.

hgzimmerman avatar hgzimmerman commented on May 26, 2024

Ah, the syntax rules around fragment capture sections differs slightly from those in the path.
{*} isn't valid because there isn't any significant / to use as a separator because separators aren't used in this context.

So instead, just #[to="{*:_path}#{app_route}"] should at least compile.

from yew_router.

jetli avatar jetli commented on May 26, 2024

React router uses HashRouter/BrowserRouter/StaticRouter to support different strategies, and uses basename='/path/to/subfolder/' to support subfolder scenario like gh-pages, we might steal some ideas from that.

from yew_router.

hgzimmerman avatar hgzimmerman commented on May 26, 2024

I do admit, what we currently have is pretty obtuse when it comes to supporting fragments (if it works at all)

Because agents make heavy use of type parameters to ensure they operate as singletons, I don't want to introduce other type parameters to indicate behavior because it would make every other construct have to inherit those parameters exactly, otherwise users would end up with duplicate agents that don't talk to every dependent component. So I can't specify behavior using type parameters.

The next logical thing to do would be to have a message set some state of the router to configure its basename and routing strategy.
I don't love this because it moves the API in an imperative direction while the router should be mostly a declarative construct.

from yew_router.

hgzimmerman avatar hgzimmerman commented on May 26, 2024

I do think that at least supporting a basename and strategy enum in the service would be a good start.
After that, allowing sending messages to the router to configure it would be the next step.

I do want to try my suggestion above though. Unfortunately, the derive macro doesn't handle type parameters so I can't just support a generic adapter that converts normal routes to fragments. I'll try to fix that first, but if it proves too difficult, I'll pivot to working with the stateful configuration.

from yew_router.

jetli avatar jetli commented on May 26, 2024

References for basename from react router api

<BrowserRouter basename="/calendar" />
<Link to="/today"/> // renders <a href="/calendar/today">

<HashRouter basename="/calendar"/>
<Link to="/today"/> // renders <a href="#/calendar/today">

from yew_router.

hgzimmerman avatar hgzimmerman commented on May 26, 2024

I don't think that separate BrowserRouter and HashRouters would be maintained here, given that a basename could just as easily be "#/calendar".

The problem with this is that because both the Router and links/buttons use agents to manage shared state, there isn't a way to make the message used to set state on the agent private. This would allow some unrelated piece of code to reconfigure the agent from an arbitrary point in the application with very little transparency that it is happening at runtime.
This would cause similar problems if someone tried to use two or more Routers at once with differing basenames.

And if the component owning the Router is recreated, the Router would try to redundantly set the basename again when it itself is recreated.

Its not the largest foot-gun, but one I would like to avoid. I'm going to prefer an alternative solution if possible. If not, I'll look at this and likely emit a log to console when the basename is set.

from yew_router.

jetli avatar jetli commented on May 26, 2024

Yep, no need to separate them, just refer to some render rules :)

from yew_router.

hgzimmerman avatar hgzimmerman commented on May 26, 2024

What I currently plan to do with respect to this issue is to attempt to include the provided wrapper I described above.

I intend to include a small corresponding example demonstrating its use.

The implementation problem is that the Switch macro can't be called from within yew_router itself, so I plan to use cargo expand to generate the implementation and copy + paste its contents into the project and tidy them up a bit.

from yew_router.

hgzimmerman avatar hgzimmerman commented on May 26, 2024

As mentioned above, testing indicated that a fragment adapter as specified above would not work.

So parsing rules were relaxed, and now the proper form should be:

#[derive(Switch, Debug, Clone, PartialEq)]
#[to = "{*:path}#{*:route}"]
pub struct FragmentAdapter<W: Switch> {
    path: String,
    route: W,
}

You would probably either replace the leading {*:path} (and its respective field) with the route your app is served from or use a function to create the adapters with a constant string representing the path your app is served from like:

const YOUR_APPLICATION_PATH: &str = "/rust-yew-realworld-example-app/";
fn make_route(route: AppRoute) -> FragmentAdapter<AppRoute> {
    FragmentAdapter {
        path: YOUR_APPLICATION_PATH.to_string(),
        route
    }
}

from yew_router.

jetli avatar jetli commented on May 26, 2024

Nice, I'll try later

from yew_router.

hgzimmerman avatar hgzimmerman commented on May 26, 2024

Let me know if you have any problems and I'll reopen this Issue.

from yew_router.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.