-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Client-side storage / State integration #1629
Conversation
Extend State to allow the storage of select Vars in the user's browser. At compile time, extract all `rx.Cookie` and `rx.LocalStorage` typed state Vars and save them in `/utils/context.js` as `clientStorage` for access on the frontend. When `rx.Cookie` or `rx.LocalStorage` values are set on the backend, the frontend will also set them in the appropriate browser store based on the delta received over the websocket. The clientStorage object provides options and other information about how to persist the vars. During initial hydrate event, values in the browser store will be read on the frontend and sent to the backend as part of the event payload to be applied to the state with HydrateMiddleware. REF-172
Clean up and use a LocalStorage access helper found on stack overflow for use in integration tests. Move the `poll_for_navigation` contextmanager to new `utils` module so that it can be more easily shared among integration tests.
Test rx.Cookie and rx.LocalStorage APIs with selenium
3d3ffc2
to
016be96
Compare
CI tests take longer, so get more of a buffer to avoid flaky test
Ensure that cookies do not persist on the backend after the user clears their browser storage. Only values sent from the browser to the backend during hydrate will be available in the state.
ensure that cookies are set with root path to avoid access issues. fix #1628
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks nice, good job!
@picklelo ready for review when you get a chance. |
@@ -1110,3 +1127,104 @@ def _convert_mutable_datatypes( | |||
) | |||
|
|||
return field_value | |||
|
|||
|
|||
class ClientStorageBase: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these inherit from rx.Base
to get Pydantic support? Most of our other classes inherit from there
secure: bool | None | ||
same_site: str | ||
|
||
def __new__( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we use __new__
instead of __init__
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these two classes extend str
, which is immutable, and thus cannot override __init__
to set values.
inst = super().__new__(cls, object, encoding or "utf-8", errors or "strict") | ||
else: | ||
inst = super().__new__(cls, object) | ||
inst.name = name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we use the rx.Base
we shouldn't need to explicitly set these as it will handle it automatically
Extend State to allow the storage of select Vars in the user's browser.
At compile time, extract all
rx.Cookie
andrx.LocalStorage
typed state Varsand save them in
/utils/context.js
asclientStorage
for access on thefrontend.
When
rx.Cookie
orrx.LocalStorage
values are set on the backend, thefrontend will also set them in the appropriate browser store based on the delta
received over the websocket. The
clientStorage
object provides options andother information about how to persist the vars.
During initial hydrate event, values in the browser store will be read on the
frontend and sent to the backend as part of the event payload to be applied to
the state with
HydrateMiddleware
.REF-172
Sample code
(see also
integration/test_client_side.py
)TODO