pub fn thaw(&self, new_frozen_app: &str, thaw_prefs: ThawPrefs) -> Result<(), ClientError> {
        let new_frozen_app: FrozenApp = serde_json::from_str(new_frozen_app)
            .map_err(|err| ClientError::ThawFailed { source: err })?;
        let route = new_frozen_app.route.clone();
        // Set everything in the render context
        let mut frozen_app = self.frozen_app.borrow_mut();
        *frozen_app = Some((new_frozen_app, thaw_prefs));
        // I'm not absolutely certain about destructor behavior with navigation or how
        // that could change with the new primitives, so better to be safe than sorry
        drop(frozen_app);

        // Check if we're on the same page now as we were at freeze-time
        let curr_route = match &*self.router.get_load_state_rc().get_untracked() {
                RouterLoadState::Loaded { path, .. } => path.clone(),
                RouterLoadState::Loading { path, .. } => path.clone(),
                // We're in an error state, so we have no choice but to go to the old route
                RouterLoadState::ErrorLoaded { location } => todo!("thawing while in an error state is not yet implemented"),
                // The user is trying to thaw on the server, which is an absolutely horrific idea (we should be generating state, and loops could happen)
                RouterLoadState::Server => panic!("attempted to thaw frozen state on server-side (you can only do this in the browser)"),
            };
        // We handle the possibility that the page tried to reload before it had been
        // made interactive here (we'll just reload wherever we are)
        if let Some(route) = route {
            // If we're on the same page, just reload, otherwise go to the frozen route
            if curr_route == route {
                self.router.reload();
            } else {
                navigate(&route);
            }
        } else {
            // The page froze before hydration, so we'll jsut reload
            self.router.reload();
        }

        Ok(())
    }
Commands Perseus to 'thaw' the app from the given frozen state. You'll
also need to provide preferences for thawing, which allow you to control
how different pages should prioritize frozen state over existing (or
*active*) state. Once you call this, assume that any following logic
will not run, as this may navigate to a different route in your app. How
you get the frozen state to supply to this is up to you.

If the app has already been thawed from a previous frozen state, any
state used from that will be considered *active* for this thawing.

This will return an error if the frozen state provided is invalid.
However, if the frozen state for an individual page is invalid, it will
be silently ignored in favor of either the active state or the
server-provided state.

If the app was last frozen while on an error page, this will not attempt
to change the current route.
packages/perseus/src/template/render_ctx.rs