ReactiveStateSchema

As the name suggests, the ReactiveStateSchema class is used to define the schema of a state object. The state object is strongly-typed, so the schema is responsible for defining all the fields, their types, and their default values. The type of the field is defined by the API method which is used to add it. See the :Add*Field() method documentation below. Any value assigned to a state property will be checked against the schema at assignment time and result in an error if it’s of the wrong type. All state changes are tracked based on simple equality checks between values.

Field Data Types

State objects support a variety of different types of properties as described below.

Simple Data Types

Each of the simple data types (string, number, boolean) can be added either as a required (non-nil) field with a default value, or as an optional (nillable) field where the default is nil.

Enums

LibTSMUtil provides an enum type which can also be added as state fields (either optional or not). The user-defined enum type is provided when adding an enum field. This allows the field to be constrained to a specific enum type, as opposed to allowing values of any enum type.

Optional Table

Optional table fields can be added to store more complex context which isn’t as strictly type-checked on the state object. Note that since changes are checked when assigning to the state property, changing a field within a table property does not result in that change propagating to publishers which are observing the state. Similarly, assigning the same table to a table property does not result in a change being observed. In practice, optional table fields are used to store context that is associated with the state, but is not necessarily being observed for changes.

Optional Class

Optional class fields behave very similarly to optional table fields. The main reason they are provided over just treating class objects as tables (which they are) is for type checking and enhanced language server support.

Extending

There are situations where state schemas are associated with classes, especially for UI components where it’s common for there to also be subclasses. In these cases, the state schema provides a simple mechanism for the subclasses to extend the schema of their parent class to avoid needing to redefine the same fields and potentially introduce bugs if the child state schema doesn’t satisfy the requirements of the parent class.

This is accomplished with the :Extend() method which creates a new state schema object that inherits all the fields of the original schema. New fields can then be added as normal, but also the default values of existing fields can be changed via the :UpdateFieldDefault() method.

Example

Below is an exmaple of defining a simple state schema for text and button UI components.

local TEXT_STATE_SCHEMA = Reactive.CreateStateSchema("TEXT_STATE")
   :AddStringField("justifyH", "LEFT")
   :AddStringField("text", "")
   :Commit()

local BUTTON_STATE_SCHEMA = TEXT_STATE_SCHEMA:Extend("BUTTON_STATE")
   :UpdateFieldDefault("justifyH", "CENTER")
   :AddBooleanField("enabled", true)
   :Commit()

Memory Management

The ReactiveStateSchema objects are intended to never be GC’d and have a static lifecycle (i.e. one that’s equal to the lifecycle of the application), but there is nothing preventing them from being GC’d (assuming there are no state objects with a reference to them).

API

class ReactiveStateSchema: Class
staticmethod Create(name: string): ReactiveStateSchema

Creates a new state schema object.

Parameters:

name (string) – The name for debugging purposes

AddStringField(
    self: ReactiveStateSchema,
    key: string,
    default: string,
    validateFunc?: fun(value: string): boolean
): ReactiveStateSchema

Defines a string field as part of the schema.

Parameters:
  • key (string) – The key of the new field

  • default (string) – The default value of the field

  • validateFunc? (fun(value: string): boolean) – A function used to validate values

AddOptionalStringField(
    self: ReactiveStateSchema,
    key: string,
    validateFunc?: fun(value: string): boolean
): ReactiveStateSchema

Defines a string field as part of the schema which can be nil (and is by default).

Parameters:
  • key (string) – The key of the new field

  • validateFunc? (fun(value: string): boolean) – A function used to validate values

AddNumberField(
    self: ReactiveStateSchema,
    key: string,
    default: number,
    validateFunc?: fun(value: number): boolean
): ReactiveStateSchema

Defines a number field as part of the schema.

Parameters:
  • key (string) – The key of the new field

  • default (number) – The default value of the field

  • validateFunc? (fun(value: number): boolean) – A function used to validate values

AddOptionalNumberField(
    self: ReactiveStateSchema,
    key: string,
    validateFunc?: fun(value: number): boolean
): ReactiveStateSchema

Defines a number field as part of the schema which can be nil (and is by default).

Parameters:
  • key (string) – The key of the new field

  • validateFunc? (fun(value: number): boolean) – A function used to validate values

AddBooleanField(
    self: ReactiveStateSchema,
    key: string,
    default: boolean
): ReactiveStateSchema

Defines a boolean field as part of the schema.

Parameters:
  • key (string) – The key of the new field

  • default (boolean) – The default value of the field

AddOptionalBooleanField(self: ReactiveStateSchema, key: string): ReactiveStateSchema

Defines a boolean field as part of the schema which can be nil (and is by default).

Parameters:

key (string) – The key of the new field

AddOptionalTableField(
    self: ReactiveStateSchema,
    key: string,
    validateFunc?: fun(value: table): boolean
): ReactiveStateSchema

Defines a table field as part of the schema which can be nil (and is by default).

Parameters:
  • key (string) – The key of the new field

  • validateFunc? (fun(value: table): boolean) – A function used to validate values

AddEnumField(
    self: ReactiveStateSchema,
    key: string,
    enumType: EnumObject,
    default: EnumValue
): ReactiveStateSchema

Defines an enum field field as part of the schema.

Parameters:
  • key (string) – The key of the new field

  • enumType (EnumObject) – The enum type

  • default (EnumValue) – The default value of the field

AddOptionalEnumField(
    self: ReactiveStateSchema,
    key: string,
    enumType: EnumObject
): ReactiveStateSchema

Defines an enum field field as part of the schema which can be nil (and is by default).

Parameters:
  • key (string) – The key of the new field

  • enumType (EnumObject) – The enum type

AddOptionalClassField(
    self: ReactiveStateSchema,
    key: string,
    class: string | <T>
): ReactiveStateSchema

Defines an optional class field as part of the schema which can be nil (and is by default).

Parameters:
  • key (string) – The key of the new field

  • class (string | <T>) – The class or name of the class (subclasses are not permitted in the later case)

UpdateFieldDefault(self: ReactiveStateSchema, key: string, default: any): ReactiveStateSchema

Updates the default value of an existing field.

Parameters:
  • key (string) – The key of the field

  • default (any) – The default value of the field

Commit(self: ReactiveStateSchema): ReactiveStateSchema

Commits the schema and prevents further changes.

CreateState(self: ReactiveStateSchema): ReactiveState

Creates a state object based on the schema.

Extend(self: ReactiveStateSchema, name: string): ReactiveStateSchema

Returns a new state schema which extends the existing one

Parameters:

name (string) – The name of the extended schema