diff --git a/examples/basic/.perseus/src/lib.rs b/examples/basic/.perseus/src/lib.rs index a93b3e927f..121f5252cf 100644 --- a/examples/basic/.perseus/src/lib.rs +++ b/examples/basic/.perseus/src/lib.rs @@ -10,7 +10,7 @@ use perseus::{ shell::{app_shell, get_initial_state, get_render_cfg, InitialState, ShellProps}, }, plugins::PluginAction, - state::GlobalState, + state::PageStateStore, templates::{RouterState, TemplateNodeType}, DomNode, }; @@ -65,8 +65,8 @@ pub fn run() -> Result<(), JsValue> { // Create the router state we'll need let router_state = RouterState::default(); - // Create a global state to use - let global_state = GlobalState::default(); + // Create a page state store to use + let pss = PageStateStore::default(); // Create the router we'll use for this app, based on the user's app definition create_app_route! { @@ -90,7 +90,7 @@ pub fn run() -> Result<(), JsValue> { // Sycamore's reactivity is broken by a future, so we need to explicitly add the route to the reactive dependencies here // We do need the future though (otherwise `container_rx` doesn't link to anything until it's too late) let _ = route.get(); - wasm_bindgen_futures::spawn_local(cloned!((locales, route, container_rx, router_state, global_state, translations_manager, error_pages, initial_container) => async move { + wasm_bindgen_futures::spawn_local(cloned!((locales, route, container_rx, router_state, pss, translations_manager, error_pages, initial_container) => async move { let container_rx_elem = container_rx.get::().unchecked_into::(); checkpoint("router_entry"); match &route.get().as_ref().0 { @@ -113,7 +113,7 @@ pub fn run() -> Result<(), JsValue> { error_pages: error_pages.clone(), initial_container: initial_container.unwrap().clone(), container_rx_elem: container_rx_elem.clone(), - global_state: global_state.clone() + page_state_store: pss.clone() } ).await, // If the user is using i18n, then they'll want to detect the locale on any paths missing a locale diff --git a/examples/rx_state/src/about.rs b/examples/rx_state/src/about.rs index b33bb83c7b..a06f8e1f8a 100644 --- a/examples/rx_state/src/about.rs +++ b/examples/rx_state/src/about.rs @@ -7,11 +7,11 @@ use sycamore::view::View; #[perseus::template(AboutPage)] #[component(AboutPage)] pub fn about_page() -> View { - // Get the global state manually - let global_state = get_render_ctx!().global_state; + // Get the page state store manually + let pss = get_render_ctx!().page_state_store; // Get the state from the index page // If the user hasn't visited there yet, this won't exist - let username = match global_state.get::() { + let username = match pss.get::() { Some(IndexPropsRx { username }) => username, None => Signal::new("".to_string()), }; diff --git a/packages/perseus-macro/src/template.rs b/packages/perseus-macro/src/template.rs index 0671232200..e915d0858b 100644 --- a/packages/perseus-macro/src/template.rs +++ b/packages/perseus-macro/src/template.rs @@ -210,17 +210,18 @@ pub fn template_with_rx_state_impl(input: TemplateFn, attr_args: AttributeArgs) ::sycamore::prelude::view! { #component_name( { - // Check if properties of the reactive type are already in the global state + // Check if properties of the reactive type are already in the page state store // If they are, we'll use them (so state persists for templates across the whole app) - let mut global_state = ::perseus::get_render_ctx!().global_state; - match global_state.get() { + // TODO Isolate this for pages + let mut pss = ::perseus::get_render_ctx!().page_state_store; + match pss.get() { Some(old_state) => old_state, None => { // If there are props, they will always be provided, the compiler just doesn't know that // If the user is using this macro, they sure should be using `#[make_rx(...)]` or similar! let rx_props = ::serde_json::from_str::<#unrx_ty>(&props.unwrap()).unwrap().make_rx(); // They aren't in there, so insert them - global_state.add(rx_props.clone()); + pss.add(rx_props.clone()); rx_props } } diff --git a/packages/perseus/src/build.rs b/packages/perseus/src/build.rs index 3a264f2261..b0b8b73cf3 100644 --- a/packages/perseus/src/build.rs +++ b/packages/perseus/src/build.rs @@ -3,7 +3,7 @@ use crate::errors::*; use crate::locales::Locales; use crate::router::RouterState; -use crate::state::GlobalState; +use crate::state::PageStateStore; use crate::templates::TemplateMap; use crate::translations_manager::TranslationsManager; use crate::translator::Translator; @@ -124,7 +124,7 @@ async fn gen_state_for_path( translator, true, RouterState::default(), - GlobalState::default(), + PageStateStore::default(), ) }); // Write that prerendered HTML to a static file @@ -159,7 +159,7 @@ async fn gen_state_for_path( translator, true, RouterState::default(), - GlobalState::default(), + PageStateStore::default(), ) }); // Write that prerendered HTML to a static file @@ -204,7 +204,7 @@ async fn gen_state_for_path( translator, true, RouterState::default(), - GlobalState::default(), + PageStateStore::default(), ) }); let head_str = template.render_head_str(None, translator); diff --git a/packages/perseus/src/lib.rs b/packages/perseus/src/lib.rs index ee79c5730b..b33f2741c6 100644 --- a/packages/perseus/src/lib.rs +++ b/packages/perseus/src/lib.rs @@ -48,13 +48,13 @@ mod decode_time_str; mod default_headers; mod error_pages; mod export; -mod global_state; mod html_shell; mod locale_detector; mod locales; mod log; mod macros; mod page_data; +mod page_state_store; mod path_prefix; mod router; mod server; @@ -98,7 +98,7 @@ pub mod templates { // TODO (v0.4.0) Refactor to put several more things inside here (everything to do with generation functions) /// Utilities for working with state. pub mod state { - pub use crate::global_state::GlobalState; + pub use crate::page_state_store::PageStateStore; } /// A series of exports that should be unnecessary for nearly all uses of Perseus. These are used principally in developing alternative /// engines. diff --git a/packages/perseus/src/global_state.rs b/packages/perseus/src/page_state_store.rs similarity index 83% rename from packages/perseus/src/global_state.rs rename to packages/perseus/src/page_state_store.rs index a79f71b55e..6b18bb9e24 100644 --- a/packages/perseus/src/global_state.rs +++ b/packages/perseus/src/page_state_store.rs @@ -3,20 +3,18 @@ use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; -/// A container for global state in Perseus. This is designed as a context store, in which one of each type can be stored. Therefore, it acts very similarly to Sycamore's context system, -/// though it's specifically designed for each template to store one reactive properties object. In theory, you could interact with this entirely independently of Perseus' state interface, +/// A container for page state in Perseus. This is designed as a context store, in which one of each type can be stored. Therefore, it acts very similarly to Sycamore's context system, +/// though it's specifically designed for each page to store one reactive properties object. In theory, you could interact with this entirely independently of Perseus' state interface, /// though this isn't recommended. -/// -/// For now, `struct`s stored in global state should have their reactivity managed by the inserter (usually the Perseus interface). However, this will change radically when Sycamore's -/// proposals for fine-grained reactivity are stabilized. +// TODO Make this work with multiple pages for a single template #[derive(Default, Clone)] -pub struct GlobalState { +pub struct PageStateStore { /// A map of type IDs to anything, allowing one storage of each type (each type is intended to a properties `struct` for a template). Entries must be `Clone`able becasue we assume them /// to be `Signal`s or `struct`s composed of `Signal`s. // Technically, this should be `Any + Clone`, but that's not possible without something like `dyn_clone`, and we don't need it because we can restrict on the methods instead! map: Rc>>>, } -impl GlobalState { +impl PageStateStore { /// Gets an element out of the state by its type. pub fn get(&self) -> Option { let type_id = TypeId::of::(); diff --git a/packages/perseus/src/server/render.rs b/packages/perseus/src/server/render.rs index 55bc3f6dfd..46eca88e84 100644 --- a/packages/perseus/src/server/render.rs +++ b/packages/perseus/src/server/render.rs @@ -2,7 +2,7 @@ use crate::decode_time_str::decode_time_str; use crate::errors::*; use crate::page_data::PageData; use crate::router::RouterState; -use crate::state::GlobalState; +use crate::state::PageStateStore; use crate::stores::{ImmutableStore, MutableStore}; use crate::template::{States, Template, TemplateMap}; use crate::translations_manager::TranslationsManager; @@ -82,7 +82,7 @@ async fn render_request_state( translator, true, RouterState::default(), - GlobalState::default(), + PageStateStore::default(), ) }); let head = template.render_head_str(state.clone(), translator); @@ -173,7 +173,7 @@ async fn revalidate( translator, true, RouterState::default(), - GlobalState::default(), + PageStateStore::default(), ) }); let head = template.render_head_str(state.clone(), translator); @@ -293,7 +293,7 @@ pub async fn get_page_for_template( &translator, true, RouterState::default(), - GlobalState::default(), + PageStateStore::default(), ) }); let head_val = template.render_head_str(state.clone(), &translator); diff --git a/packages/perseus/src/shell.rs b/packages/perseus/src/shell.rs index ca9f2060b0..dcc0101fc0 100644 --- a/packages/perseus/src/shell.rs +++ b/packages/perseus/src/shell.rs @@ -3,7 +3,7 @@ use crate::error_pages::ErrorPageData; use crate::errors::*; use crate::page_data::PageData; use crate::path_prefix::get_path_prefix_client; -use crate::state::GlobalState; +use crate::state::PageStateStore; use crate::template::Template; use crate::templates::{RouterLoadState, RouterState, TemplateNodeType}; use crate::ErrorPages; @@ -224,8 +224,8 @@ pub struct ShellProps { pub locale: String, /// The router state. pub router_state: RouterState, - /// The global state. - pub global_state: GlobalState, + /// The template state store. + pub page_state_store: PageStateStore, /// A *client-side* translations manager to use (this manages caching translations). pub translations_manager: Rc>, /// The error pages, for use if something fails. @@ -246,7 +246,7 @@ pub async fn app_shell( was_incremental_match, locale, router_state, - global_state, + page_state_store, translations_manager, error_pages, initial_container, @@ -317,7 +317,7 @@ pub async fn app_shell( translator, false, router_state_2, - global_state, + page_state_store, ) }, &container_rx_elem, @@ -332,7 +332,7 @@ pub async fn app_shell( translator, false, router_state_2, - global_state, + page_state_store, ) }, &container_rx_elem, @@ -426,7 +426,7 @@ pub async fn app_shell( translator, false, router_state_2.clone(), - global_state, + page_state_store, ) }, &container_rx_elem, @@ -441,7 +441,7 @@ pub async fn app_shell( translator, false, router_state_2, - global_state, + page_state_store, ) }, &container_rx_elem, diff --git a/packages/perseus/src/template.rs b/packages/perseus/src/template.rs index af0add54fa..4cd0cce324 100644 --- a/packages/perseus/src/template.rs +++ b/packages/perseus/src/template.rs @@ -2,8 +2,8 @@ use crate::default_headers::default_headers; use crate::errors::*; -use crate::global_state::GlobalState; use crate::router::RouterState; +use crate::state::PageStateStore; use crate::translator::Translator; use crate::Html; use crate::Request; @@ -29,9 +29,10 @@ pub struct RenderCtx { pub translator: Translator, /// The router's state. pub router: RouterState, - /// The global state for the app. This is a type map to which templates can add state that they need to access at a later time. Typically, interfacing with this will be done - /// through the automation of the `#[perseus::template_with_rx_state(...)]` macro, but it can be used manually as well. - pub global_state: GlobalState, + /// The page state store for the app. This is a type map to which pages can add state that they need to access later. Usually, this will be interfaced with through + /// the `#[perseus::template_with_rx_state(...)]` macro, but it can be used manually as well to get the state of one page from another (provided that the target page has already + /// been visited). + pub page_state_store: PageStateStore, } /// Represents all the different states that can be generated for a single template, allowing amalgamation logic to be run with the knowledge @@ -239,7 +240,7 @@ impl Template { translator: &Translator, is_server: bool, router_state: RouterState, - global_state: GlobalState, + page_state_store: PageStateStore, ) -> View { view! { // We provide the translator through context, which avoids having to define a separate variable for every translation due to Sycamore's `template!` macro taking ownership with `move` closures @@ -248,7 +249,7 @@ impl Template { is_server, translator: translator.clone(), router: router_state, - global_state + page_state_store }, children: || (self.template)(props) }) @@ -266,9 +267,9 @@ impl Template { // It's also only ever run on the server is_server: true, translator: translator.clone(), - // The head string is rendered to a string, and so never has information about router or global state + // The head string is rendered to a string, and so never has information about router or page state router: RouterState::default(), - global_state: GlobalState::default() + page_state_store: PageStateStore::default() }, children: || (self.head)(props) })