Skip to content

Commit

Permalink
docs(book): wrote docs on state thawing
Browse files Browse the repository at this point in the history
  • Loading branch information
arctic-hen7 committed Jan 24, 2022
1 parent ce07134 commit 2d67a40
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/next/en-US/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
- [Reactive State](/docs/reference/state/rx)
- [Global State](/docs/reference/state/global)
- [State Freezing](/docs/reference/state/freezing)
- [Freezing to IndexedDB](/docs/reference/state/idb-freezing)
- [CLI](/docs/reference/cli)
- [Ejecting](/docs/reference/ejecting)
- [Snooping](/docs/reference/snooping)
Expand Down
8 changes: 4 additions & 4 deletions docs/next/en-US/reference/state/freezing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

If you use the reactive and global state systems to their full potential, your entire app can be represented as its state. So what if you could make all that state unreactive again, serialize it to a string, and keep it for later? Well, you'd be able to let your users pick up at the *exact* same place they were when they come back later. Imagine you're in the middle of filling out some forms and then your computer crashes. You boot back up and go to the website you were on. If it's built with Perseus and state freezing occurred just before the crash, you're right back to where you were. Same page, same inputs, same everything.

Specifically, Perseus achieves this by serializing the global state and the page state store, along with the route that the user's currently on. You can invoke this easily by running `.freeze()` on the render context, which you can access with `perseus::get_render_ctx!()`. Best of all, if state hasn't been used yet (e.g. a page ahsn't been visited), it won't be cached, because it doesn't need to be. That also applies to global state, meaning the size of your frozen output is minimized.
Specifically, Perseus achieves this by serializing the global state and the page state store, along with the route that the user's currently on. You can invoke this easily by running `.freeze()` on the render context, which you can access with `perseus::get_render_ctx!()`. Best of all, if state hasn't been used yet (e.g. a page hasn't been visited), it won't be cached, because it doesn't need to be. That also applies to global state, meaning the size of your frozen output is minimized.

## Example

Expand All @@ -14,8 +14,8 @@ You can easily imperatively instruct your app to freeze itself like so (see [her

## Thawing

Recovering your app's state from a frozen state is called *thawing* in Perseus (basically like hydration for state, but remember that hydration is for views and thawing is for state!), and it's completely automatic. Once you give Perseus a way to get your frozen state, it'll check when your app loads up and thaw as necessary.
Recovering your app's state from a frozen state is called *thawing* in Perseus (basically like hydration for state, but remember that hydration is for views and thawing is for state!), and it can occur gradually and automatically once you provide Perseus a frozen state to use, which you can do by calling `.thaw()` on the render context (which you can get with `perseus::get_render_ctx!()`). How you store and retrieve frozen state is entirely up to you. For example, you could store the user's last state in a database and then fetch that when the user logs in, or you could store it in IndexedDB and have even logging in be covered by it (if authentication tokens are part of your global state).

*The process of telling Perseus how to get frozen state is still in development, but it'll be ready for v0.3.3!*
One important thing to understand about thawing though is how Perseus decided what state to use for a template, because there can be up to three options. Every template that accepts state will have generated state that's provided to it from the generation proceses on the server, but there could also be a frozen state and an active state (some state that's already been made reactive). The server-generated state is always the lowest priority, and it will be used if no active or frozen state is available. However, deciding between frozen and active state is more complicated. If only one is available, it will of course be used, but it both are available, the choice is yours. You can represent this choice through the `ThawPrefs` `struct`, which must be provided to a call to `.thaw()` as the second argument. This has two fields, one for page state, and another for global state. For global state, you can set the `global_prefers_frozen` field to `true` if you want to override active global state with a frozen one. For page state, you'll use `PageThawPrefs`, which can be set to `IncludeAll` (all pages will prefer frozen state), `Include(Vec<String>)` (the listed pages will prefer frozen state, all others will prefer active state), or `Exclude(Vec<String>)` (the listed pages will prefer active state, all others will prefer frozen state). There's no `ExcludeAll` option because that would defeat the entire purpose of thawing.

TODO
It may at first be tempting to use `IncludeAll`, but this is an important UX decision that you should consider carefully. Using frozen state when active state isn't available is automatic, but preferring frozen state *over* active state translates to something like this: a user does some stuff, then state is thawed, everything they did at the start is gone and replaced with whatever they did in the previous session. This might be entirely reasonable in pages that can only be accessed after thawing is complete, but in pages that are accessible at all times, this could be extremely irritating to your users!
7 changes: 7 additions & 0 deletions docs/next/en-US/reference/state/idb-freezing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Freezing to IndexedDB

One of the most common places to store frozen state is inside the browser, which can be done with Perseus' inbuilt `IdbFrozenStateStore` system, which uses [IndexedDB]() to store as many frozen states as you want, allowing you to revert to not just the previous state, but the one before that, the one before that, etc.

To use this system, you'll need to enable the `idb-freezing` feature flag, and then you can use the system as per the below example.

*Further documentation on this system will be written after it's been built, which it will be by v0.3.3. Sorry for the wait!*

0 comments on commit 2d67a40

Please sign in to comment.