Attribute Macro perseus::make_rx

source · []
#[make_rx]
Expand description

Processes the given struct to create a reactive version by wrapping each field in a Signal. This will generate a new struct with the given name and implement a .make_rx() method on the original that allows turning an instance of the unreactive struct into an instance of the reactive one.

This macro automatically derives serde::Serialize and serde::Deserialize on the original struct, so do NOT add these yourself, or errors will occur. Note that you can still use Serde helper macros (e.g. #[serde(rename = "testField")]) as usual. Clone will also be derived on both the original and the new struct, so do NOT try to derive it yourself.

If one of your fields is itself a struct, by default it will just be wrapped in a Signal, but you can also enable nested fine-grained reactivity by adding the #[rx::nested("field_name", FieldTypeRx)] helper attribute to the struct (not the field, that isn’t supported by Rust yet), where field_name is the name of the field you want to use ensted reactivity on, and FieldTypeRx is the wrapper type that will be expected. This should be created by using this macro on the original struct type.

Note that this will be deprecated or significantly altered by Sycamore’s new observables system (when it’s released). For that reason, this doesn’t support more advanced features like leaving some fields unreactive, this is an all-or-nothing solution for now.

Examples

use serde::{Serialize, Deserialize};
use perseus::make_rx;
// We need this trait in scope to manually invoke `.make_rx()`
use perseus::state::MakeRx;

#[make_rx(TestRx)]
// Notice that we don't need to derive `Serialize`,`Deserialize`, or `Clone`, the macro does it for us
#[rx::nested("nested", NestedRx)]
struct Test {
    #[serde(rename = "foo_test")]
    foo: String,
    bar: u16,
    // This will get simple reactivity
    baz: Baz,
    // This will get fine-grained reactivity
    // We use the unreactive type in the declaration, and tell the macro what the reactive type is in the annotation above
    nested: Nested
}
// On unreactive types, we'll need to derive `Serialize` and `Deserialize` as usual
#[derive(Serialize, Deserialize, Clone)]
struct Baz {
    test: String
}
#[perseus_macro::make_rx(NestedRx)]
struct Nested {
    test: String
}

let new = Test {
    foo: "foo".to_string(),
    bar: 5,
    baz: Baz {
        // We won't be able to `.set()` this
        test: "test".to_string()
    },
    nested: Nested {
        // We will be able to `.set()` this
        test: "nested".to_string()
    }
}.make_rx();
// Simple reactivity
new.bar.set(6);
// Simple reactivity on a `struct`
new.baz.set(Baz {
    test: "updated".to_string()
});
// Nested reactivity on a `struct`
new.nested.test.set("updated".to_string());
// Our own derivations still remain
let _new_2 = new.clone();