Skip to content

Commit

Permalink
describe struct API in README
Browse files Browse the repository at this point in the history
  • Loading branch information
andrfra committed Apr 15, 2024
1 parent 4898088 commit cd758ad
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 8 deletions.
76 changes: 75 additions & 1 deletion packages/reactivity-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,81 @@ map.set("foo", "bar"); // effect prints "bar"

#### Struct

TODO
Previously we described how you can create objects with reactive properties using `reactive` and `computed`.
For example a person having a first name, a last name and computed property computing the full name, whenever first or last name changes.

The reactivity API helps you to create such reactive objects by providing a function called `reactiveStruct`.

For example, to create a person with `reactiveStruct` proceed as follows:

```ts
import { reactiveStruct } from "@conterra/reactivity-core";

// declare a type for the reactive object
type PersonType = {
firstName: string;
lastName: string;
}
// define a class like PersonClass
const PersonClass = reactiveStruct<PersonType>().define({
firstName: {}, // default options (reactive and writable)
lastName: { writable: false } // read-only
});
// create a new reactive instance
const person = new PersonClass({
firstName: "John",
lastName: "Doe"
});
// compute the full name
const fullName = computed(() => `${person.firstName} ${person.lastName}`);
console.log(fullName.value); // John Doe
person.firstName = "Jane";
console.log(fullName.value); // Jane Doe
```
The `define` function can be used to
- make properties read-only
- declare non reactive properties
- create computed properties
- add methods to the reactive object

The following example shows declaring an extended `Person`:

```ts
type PersonType = {
firstName: string;
lastName: string;
fullName: string; // will be a computed property
printName: () => void // a method printing the full name
}
const PersonClass = reactiveStruct<PersonType>().define({
firstName: {},
lastName: { writable: false },
fullName: {
compute() {
// executed whenever first or last name changes
return `${this.firstName} ${this.lastName}`;
}
},
printName: {
method() {
// always prints the current full name
console.log(`My name is ${this.fullName}`);
}
}
});
// create a new reactive instance
const person = new PersonClass({
firstName: "John",
lastName: "Doe"
});
person.printName(); // My name is John Doe
person.firstName = "Jane";
person.printName(); // My name is Jane Doe
```

Reactive structs are class like, as they don't support inheritance for example.
You can imagine reactive structs as simple objects having reactive properties, computed properties and methods.
Please consider writing your own classes with the basic API like `reactive` if a _class like_ is not enough.

## Why?

Expand Down
18 changes: 11 additions & 7 deletions packages/reactivity-core/struct/struct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,12 @@ export interface ReactiveStructBuilder<T> {
*
* 3. Create a new reactive struct class based on the provided definition.
* ```ts
* const PersonModel = reactiveStruct<PersonType>().define(personDefinition);
* const PersonClass = reactiveStruct<PersonType>().define(personDefinition);
* ```
*
* 4. Create a new instance of the struct.
* ```ts
* const person = new PersonModel({
* const person = new PersonClass({
* firstName: "John",
* lastName: "Doe"
* });
Expand All @@ -215,6 +215,10 @@ export interface ReactiveStructBuilder<T> {
*
* To define a read-only property set `writable` to `false`:
* ```ts
* type PersonType = {
* firstName: string;
* readonly lastName: string;
* }
* const personDefinition: ReactiveStructDefinition<PersonType> = {
* firstName: {},
* lastName: { writable: false }
Expand All @@ -224,7 +228,7 @@ export interface ReactiveStructBuilder<T> {
* firstName: "John",
* lastName: "Doe"
* });
* person.lastName = "Smith"; // throws an error
* person.lastName = "Smith"; // type error, throws error at runtime
* ```
*
* To define a non reactive property set `reactive` to `false`:
Expand Down Expand Up @@ -263,8 +267,8 @@ export interface ReactiveStructBuilder<T> {
* }
* }
* };
* const PersonModel = reactiveStruct<PersonType>().define(personDefinition);
* const person = new PersonModel({
* const PersonClass = reactiveStruct<PersonType>().define(personDefinition);
* const person = new PersonClass({
* firstName: "John",
* lastName: "Doe"
* });
Expand Down Expand Up @@ -292,8 +296,8 @@ export interface ReactiveStructBuilder<T> {
* }
* }
* };
* const PersonModel = reactiveStruct<PersonType>().define(personDefinition);
* const person = new PersonModel({
* const PersonClass = reactiveStruct<PersonType>().define(personDefinition);
* const person = new PersonClass({
* firstName: "John",
* lastName: "Doe"
* });
Expand Down

0 comments on commit cd758ad

Please sign in to comment.