Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic route vars silently shadow all other vars #3805

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

benedikt-bartscher
Copy link
Contributor

No description provided.

@abulvenz
Copy link
Contributor

Thanks for fixing. Here is my broken almost minimal example:

import reflex as rx

app = rx.App()


class State1(rx.State):
    redirect_to: str | None = None
    redirect_me: str | None = None

    def on_load(self):
        self.redirect_to = self.router.page.params.get("redirect_me")
        self.redirect_me = self.router.page.params.get("redirect_me")
        print(self)
        return rx.redirect(f"/{self.redirect_me}")


@rx.page(route="/goto/[redirect_me]", on_load=State1.on_load)
def goto() -> rx.Component:
    return rx.box(
        rx.text("Redirecting..."),
    )


@rx.page(route="/page2")
def page2() -> rx.Component:
    return rx.box(
        rx.heading("Page 2"),
        rx.text("This is page 2"),
        rx.el.pre(
        rx.text(f"Different name from route param  >>{State1.redirect_to}<<"),
        rx.text(f"Same name as route param is gone >>{State1.redirect_me}<<"),
        )
    )


def index() -> rx.Component:
    return rx.box(
        rx.heading("Hello, Reflex!"),
        rx.text("This is a test of Reflex."),
        rx.button("Go to /goto/page2", on_click=rx.redirect("/goto/page2")),
    )


app.add_page(index)

@benedikt-bartscher benedikt-bartscher changed the title dynamic routes are applied during compilation and shadow other vars Dynamic route vars silently shadow all other vars Aug 16, 2024
@benedikt-bartscher benedikt-bartscher marked this pull request as ready for review August 16, 2024 21:42
@benedikt-bartscher
Copy link
Contributor Author

There was one minor issue with multiple pages using the same dynamic argument name. It is fixed and tested now

@benedikt-bartscher
Copy link
Contributor Author

I would like to deprecate those automatically generated computed vars for dynamic routes.

  • They are untyped because the attribute is added dynamically
  • They can be easily created manually
  • There should be one good way to do things
  • They either shadow other vars or block var names (this PR)
  • They are uncached computed vars, and without usage tracking they are computed and transmitted to the frontend all the time, even if you don't need them

What's your opinion @picklelo?

Copy link
Collaborator

@masenf masenf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to deprecate those automatically generated computed vars for dynamic routes.

I could get on board with this. In most of my apps that use dynamic route vars, i typically have to add them to my state manually anyway, otherwise they cannot be referenced in some situations (like setting the page title for app.add_page).

I wonder if it makes sense to dynamically add route vars to a specific substate, rather than the root state 🤔 Something like rx.Query.redirect_me. I know we have rx.State.router.page.params["redirect_me"], but that's kind of a lot to type. Although i guess if we're going to do that, then we should just have rx.Query implement __getattr__ to return the full thing, then it would always be defined, even before the compile runs.

The other big problem I see in state.py is that substates cannot redefine or override fields from a parent state. Maybe this restriction doesn't make sense anymore... if a substate redefines a field, then it should be a different value than the same-named field in a parent state, but that's just not how the code is written today.

@benedikt-bartscher
Copy link
Contributor Author

benedikt-bartscher commented Aug 21, 2024

Thanks, @masenf, for the great ideas.
I would merge this PR as-is to prevent unwanted shadowing and create issues for further dynamic arg var decisions and substate field overwrites.

Something like rx.Query.redirect_me

I am unsure about this because it stores and transmits the same variable multiple times. All query params still live in rx.State.router. Maybe we should focus on #3681 first and later add a RouterState.params hybrid_property (#3806) to add an ergonomic alias without overhead.

The other big problem I see in state.py is that substates cannot redefine or override fields from a parent state

I totally agree 💯 I think we should change this
Edit: I just opened #3820 for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants