You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This now has the exact same syntax as the old macro and doesn't need to
have unreactive types explicitly provided to it, because it can infer
them through associated types on the new `MakeRx` and `MakeUnrx` traits.
Copy file name to clipboardExpand all lines: examples/rx_state/src/index.rs
+2-6
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
use perseus::{Html,RenderFnResultWithCause,Template};
2
2
use sycamore::prelude::*;
3
3
4
-
usecrate::global_state::{AppState,AppStateRx};
4
+
usecrate::global_state::AppStateRx;
5
5
6
6
// We define a normal `struct` and then use `make_rx` (which derives `Serialize`, `Deserialize`, and `Clone` automatically)
7
7
// This will generate a new `struct` called `IndexPropsRx` (as we asked it to), in which every field is made reactive with a `Signal`
@@ -13,11 +13,7 @@ pub struct IndexProps {
13
13
// This special macro (normally we'd use `template(IndexProps)`) converts the state we generate elsewhere to a reactive version
14
14
// We need to tell it the name of the unreactive properties we created to start with (unfortunately the compiler isn't smart enough to figure that out yet)
15
15
// This will also add our reactive properties to the global state store, and, if they're already there, it'll use the existing one
/// Exactly the same as `#[template]`, but this expects your state to be reactive (use `#[make_rx]` to make it thus). This will automatically deserialize state and make it reactive,
76
-
/// allowing you to use an MVC pattern easily in Perseus. As the second argument, you'll need to provide the name of your unreactive state `struct` (this is unergonomic,
77
-
/// but the compiler isn't smart enough to infer it yet).
78
-
///
79
-
/// Additionally, this macro will add the reactive state to the global state store, and will fetch it from there, allowing template state to persists between page changes. Additionally,
80
-
/// that state can be accessed by other templates if necessary.
81
-
// TODO Rename this to `template2` and rewrite docs on it with examples
82
75
/// The new version of `#[template]` designed for reactive state. This can interface automatically with global state, and will automatically provide Sycamore `#[component]` annotations. To
83
-
/// use this, you'll need to provide your component's name (e.g. `IndexPage`) as `#[template2(component_name = )`.
76
+
/// use this, you'll need to provide your component's name (e.g. `IndexPage`) as `#[template2(IndexPage)]` (just like with the old macro). You can also provide a custom type parameter
77
+
/// name to use for your component (defaults to `G`) as the second argument.
84
78
///
85
-
/// The first argument your template function can take is state generated for it (e.g. by the *build state* strategy). If you use this, you'll need to provide the key `unrx_props` as well to this
86
-
/// macro. The argument your template function takes should be the reactive version of your state `struct` (generated with `#[make_rx]` usually), and then you can tell us the name of unreactive
87
-
/// version with `unrx_props = `.
79
+
/// The first argument your template function can take is state generated for it (e.g. by the *build state* strategy), but the reactive version (created with `#[make_rx]` usually). From this,
80
+
/// Perseus can infer the other required types and automatically make your state reactive for you.
88
81
///
89
-
/// The second argument your template function can take is a global state generated with the `GlobalStateCreator`. If you provide this, with its type being the reactive version, you'll need to
90
-
/// provide the key `global_state = ` being the unreactive version.
82
+
/// The second argument your template function can take is a global state generated with the `GlobalStateCreator`. You should also provide the reactive type here, and Perseus will do all the
83
+
/// rest in the background.
91
84
///
92
85
/// **Warning:** this macro is currently exempt from semantic versioning, and breaking changes may be introduced here at any time! If you want stability, use the `#[template]` macro (but you won't
93
86
/// get access to Perseus' reactive state platform).
// We add a Serde derivation because it will always be necessary for Perseus on the original `struct`, and it's really difficult and brittle to filter it out
// This is only optional if the second argument wasn't provided
135
-
let global_state = if fn_args.len() == 2{
136
-
match&args.global_state{
137
-
Some(global_state) => global_state.clone(),
138
-
None => return syn::Error::new_spanned(&fn_args[0],"template functions with two arguments must declare their global state type (`global_state = `)").to_compile_error()
// This is only optional if the first argument wasn't provided
147
-
let unrx_props = if !fn_args.is_empty(){
148
-
match&args.unrx_props{
149
-
Some(unrx_props) => unrx_props.clone(),
150
-
None => return syn::Error::new_spanned(&fn_args[0],"template functions with one argument or more must declare their unreactive properties type (`unrx_props = `)").to_compile_error()
132
+
// But this is optional (we'll use `G` as the default if it's not provided)
// There's an argument for page properties that needs to have state extracted, so the wrapper will deserialize it
163
151
// We'll also make it reactive and add it to the page state store
164
152
let state_arg = &fn_args[0];
153
+
let rx_props_ty = match state_arg {
154
+
FnArg::Typed(PatType{ ty, .. }) => ty,
155
+
FnArg::Receiver(_) => unreachable!(),
156
+
};
165
157
// There's also a second argument for the global state, which we'll deserialize and make global if it's not already (aka. if any other pages have loaded before this one)
166
158
// Sycamore won't let us have more than one argument to a component though, so we sneakily extract it and literally construct it as a variable (this should be fine?)
0 commit comments