Conversation
Document the router.url attribute (a parsed URL object exposing scheme, netloc, origin, path, query, query_parameters, and fragment) and router.route_id. Add a migration table mapping each deprecated router.page.* attribute to its router.url replacement. Update the "Getting the Current Page" example in pages/overview.md to use the new API. https://claude.ai/code/session_01GTk6Ni7kyfd8VQKtq7JAXh
Greptile SummaryThis PR migrates the router documentation from the deprecated Confidence Score: 5/5Safe to merge; only finding is a minor documentation gap in the migration guide. All remaining findings are P2 documentation suggestions. The implementation is solid, the serializer bypass is correctly handled, VarData propagation is explicitly tested, and both test fixture files are consistently updated. docs/utility_methods/router_attributes.md — migration note for raw_path omits fragment. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["Frontend URL in browser\nhttps://example.com:3000/posts/123?tab=comments#top"] -->|"WebSocket router payload"| B["RouterData.from_router_data()"]
B --> C["ReflexURL (str subclass)\nstores full URL + parsed attrs"]
C -->|"_serialize_reflex_url() called eagerly\n(bypasses json.dumps str-subclass shortcut)"| D["Serialized dict\n{href, scheme, netloc, origin,\npath, query, query_parameters, fragment}"]
D -->|"State sync to frontend"| E["JS state object\nreflex_state.router.url"]
E -->|"ReflexURLCastedVar._cached_var_name"| F["router.url → url?.['href']\n(full URL string)"]
E -->|"_component('scheme').to(str)"| G["router.url.scheme → url?.['scheme']"]
E -->|"_component('query_parameters')\n.to(ObjectVar, Mapping[str,str])"| H["router.url.query_parameters\n→ url?.['query_parameters']"]
Reviews (2): Last reviewed commit: "fix(state): explicitly serialize ReflexU..." | Re-trigger Greptile |
The previous wording claimed the fragment is "usually empty" because browsers do not send it over HTTP. That is wrong for Reflex: the client template builds asPath as pathname + search + hash and ships it over the WebSocket, so router.url.fragment does reflect the current URL bar. https://claude.ai/code/session_01GTk6Ni7kyfd8VQKtq7JAXh
Merging this PR will not alter performance
Comparing Footnotes
|
Accessing rx.State.router.url.scheme (and the other parsed URL
components) previously raised VarAttributeError because ReflexURL is a
str subclass, so guess_type mapped it to StringVar, which rejects
arbitrary attribute lookup.
Introduce ReflexURLVar, a StringVar subclass that exposes each URL
component (scheme/netloc/origin/path/query/query_parameters/fragment/
href) as a typed child Var via __getattr__. The companion
ReflexURLCastedVar overrides the rendered JS expression so the Var
itself resolves to the href property at compile time, meaning
rx.text(self.router.url) renders the full URL string while
self.router.url.scheme, .path, etc. resolve to the corresponding keys
on the serialized object.
Add a dict serializer for ReflexURL so the frontend receives
{scheme, netloc, origin, path, query, query_parameters, fragment, href}
under router.url. Drop the now-unnecessary .to_string() call in the
docs sample table since the Var already renders as a URL string.
https://claude.ai/code/session_01GTk6Ni7kyfd8VQKtq7JAXh
Address review: replace the __getattr__ dispatch + component-type dict with one @Property per URL component on ReflexURLCastedVar, each annotated with the correct Var return type. This gives static typing for self.router.url.scheme / .path / .query_parameters / etc. and removes the dead __getattr__ on ReflexURLVar (all instances flow through ReflexURLCastedVar). Also tighten the regression tests: drop the unnecessary local _State class in favor of rx.State directly, and assert on both the emitted JS expression and the returned Var's _var_type so future regressions on the component typing are caught. https://claude.ai/code/session_01GTk6Ni7kyfd8VQKtq7JAXh
Address review: move .guess_type() out of _component and have each property narrow the raw ObjectItemOperation with .to(str) or .to(ObjectVar, Mapping[str, str]) instead. The .to() overloads carry accurate static return types, so StringVar / ObjectVar annotations type-check without any pyright: ignore[reportReturnType] suppressions. https://claude.ai/code/session_01GTk6Ni7kyfd8VQKtq7JAXh
Address review: ReflexURL has no .href attribute in Python, so exposing one as a Var property creates a Var-only API that doesn't exist at runtime. Drop the property. The serialized payload still carries an href key because _cached_var_name needs it to render the top-level Var as the URL string in JS, but that's an internal implementation detail and is not exposed on the Python API. https://claude.ai/code/session_01GTk6Ni7kyfd8VQKtq7JAXh
Address review: add coverage for the VarData propagation path. The casted Var and every child component Var must carry the state-context imports and hook from the underlying router state-var access, otherwise using self.router.url.scheme in a component would silently drop the state subscription at compile time. https://claude.ai/code/session_01GTk6Ni7kyfd8VQKtq7JAXh
ReflexURL is a str subclass, so json.dumps handles it natively and
never invokes the default=serialize hook registered by the framework.
This meant the enclosing RouterData serializer handed the raw
ReflexURL to json.dumps, which short-circuited it to a plain URL
string instead of the {scheme, netloc, ..., href} component dict the
frontend expects for router.url.<component> access.
Serialize the url field eagerly inside serialize_router_data so the
component dict makes it through to the frontend. Add a regression
test that goes through the real json_dumps path (not just serialize)
to catch this short-circuit in the future, and update the fixture
formatted_router in test_state.py and test_format.py to match the
new payload shape.
https://claude.ai/code/session_01GTk6Ni7kyfd8VQKtq7JAXh
|
@greptile-apps re-review |
Type of change
Description
This PR updates the documentation to reflect changes in the router API. The changes document the transition from the deprecated
router.pagenamespace to the newrouter.urlAPI androuter.route_idattribute.Key documentation updates:
Updated router attributes examples in
docs/utility_methods/router_attributes.md:router.page.*attributes with newrouter.url.*componentsrouter.url.scheme,router.url.netloc,router.url.origin,router.url.query,router.url.query_parameters, androuter.url.fragmentrouter.route_idexampleAdded comprehensive URL Attributes section documenting:
router.urlas a parsed URL objectquery_parametersAdded migration guide from deprecated
router.pageto new API:query_parametersis now a frozen mapping)Updated overview documentation in
docs/pages/overview.md:router.route_idinstead ofrouter.page.pathrouter.url.pathinstead ofrouter.page.raw_pathrouter.urldirectlyFixes #5664
Test Plan
N/A - Documentation only changes
https://claude.ai/code/session_01GTk6Ni7kyfd8VQKtq7JAXh