Methods
info
Here are valuable methods of the State Class
listed.
setKey()
Assigns a new key/name
to the State.
MY_STATE.setKey("newKey");
MY_STATE.key; // Returns 'newKey'
❓ Why a Key
- helps us during debug sessions
- makes it easier to identify the State
- no need for separate persist Key
📭 Props
Prop | Type | Default | Required |
---|---|---|---|
value | string | number | undefined | undefined | Yes |
📄 Return
State
Returns the State it was called on.
set()
We use the set()
method to mutate the current State value
.
MY_STATE.set("myNewValue");
MY_STATE.value; // Returns 'myNewValue'
👀 Hidden
Sometimes we need to update the State value in the background.
So without triggering any rerender on the Components that have bound the State to itself.
To achieve such a goal, we can set the background
property in the configuration object to true
.
MY_STATE.set("myNewValue", {background: true});
⚙️ Internal
- Ingest State Observer into the
runtime
(Observer is like an interface toruntime
) - Create State Job and add it to the
runtime
queue - Execute State Job
- Execute
sideEffects
like permanently storing the State in a Storage - Update all Subscribers of the State Observer (-> trigger rerender on subscribed Components)
📭 Props
Prop | Type | Default | Description | Required |
---|---|---|---|---|
value | ValueType = any | undefined | Value that will be assigned to the State next | Yes |
config | StateIngestConfig | {} | Configuration | No |
📄 Return
State
Returns the State it was called on.
ingest()
warning
This method is mainly thought for the internal use.
With the ingest()
method we can pass the State without any newly defined value into the runtime
.
Instead of the given value, as it happens in the set()
method,
it takes the nextStateValue
as the new State value.
MY_STATE.nextStateValue = "frank";
MY_STATE.ingest();
MY_STATE.value; // Returns 'frank'
When we ingest()
a specific extension of the State, it might behave quite different.
For instance, in case of a Computed State it will take the value
calculated by the computed function
instead of the nextStateValue
.
let coolValue = "jeff";
const MY_COMPUTED = createComputed(() => `hello ${coolValue}`); // Computed function returns 'jeff'
coolValue = "frank";
MY_COMPUTED.value; // Returns 'hello jeff'
MY_COMPUTED.ingest(); // ingest Computed into runtime and recompute value
MY_COMPUTED.value; // Returns 'hello frank'
📭 Props
Prop | Type | Default | Description | Required |
---|---|---|---|---|
config | StateIngestConfig | {} | Configuration | No |
📄 Return
State
Returns the State it was called on.
type()
warning
The type()
method has been deprecated in the latest version ^0.2.0
and is no longer available!
Why?
Reducing core
package size.
Alternative?
No. Consider using Typescript
if you want a proper typesafety.
hasCorrectType()
warning
The hasCorrectType()
method has been deprecated in the latest version ^0.2.0
and is no longer available!
Why?
Reducing core
package size.
Alternative?
No. Consider using Typescript
if you want a proper typesafety.
undo()
Reverses the latest State value
mutation.
MY_STATE.set("hi"); // State value is 'hi'
MY_STATE.set("bye"); // State value is 'bye'
MY_STATE.undo(); // State value is 'hi'
Be aware that currently, the State can only undo one State change at the time.
That's why we can't do undo().undo().undo()
to get the State value from 3 State value mutations ago.
We have planned to add a feature called history
, which will allow us to travel back in the State history
and get the previous State of the previous State, ..
📭 Props
Prop | Type | Default | Description | Required |
---|---|---|---|---|
config | StateIngestConfig | {} | Configuration | No |
📄 Return
State
Returns the State it was called on.
reset()
Resets the State. A reset includes:
- setting the State
value
to it'sinitialValue
const MY_STATE = createState("hi"); // State value is 'hi'
MY_STATE.set("bye"); // State value is 'bye'
MY_STATE.set("hello"); // State value is 'hello'
MY_STATE.reset(); //️ State value is 'hi'
📭 Props
Prop | Type | Default | Description | Required |
---|---|---|---|---|
config | StateIngestConfig | {} | Configuration | No |
📄 Return
State
Returns the State it was called on.
patch()
warning
Only relevant for States that have an object
or array
as a value type.
Merges an object with changes into the current State value
object at top-level.
const MY_STATE = createState({id: 1, name: "frank"}); // State Value is '{id: 1, name: "frank"}'
MY_STATE.patch({name: "jeff"}); // State Value is '{id: 1, name: "jeff"}'
Or if the State value
is of the type array
, and the specified argument is of the type array
too,
it concatenates the current State value
with the value of the argument.
const MY_STATE = createState([1, 2, 3]); // State Value is '[1, 2, 3]'
MY_STATE.patch([4, 5, 6]); // State Value is '[1, 2, 3, 4, 5, 6]'
If the current State value is neither an object
nor an array
, the patch can't be performed.
const MY_STATE_2 = createState(1);
MY_STATE.patch({hello: "there"}); // Error
❓ Deepmerge
Unfortunately, the patch()
method doesn't support deep merges
yet.
In conclusion, the merge only happens at the top-level of the objects.
If AgileTs can't find a particular property, it will add it at the top-level of the value object.
const MY_STATE = createState({things: { thingOne: true, thingTwo: true }});
MY_STATE.patch({ thingOne: false }); // State value is (see below)
// {things: { thingOne: true, thingTwo: true }, thingOne: false}
In case we don't want to add not existing properties to the value object,
we can set addNewProperties
to false
in the configuration object.
const MY_STATE = createState({things: { thingOne: true, thingTwo: true }});
MY_STATE.patch({ thingOne: true }, {addNewProperties: false}); // State value is (see below)
// {things: { thingOne: true, thingTwo: true }}
📭 Props
Prop | Type | Default | Description | Required |
---|---|---|---|---|
targetWithChanges | Object | undefined | Object merged into the current State value | Yes |
config | PatchConfig | {} | Configuration | No |
📄 Return
State
Returns the State it was called on.
watch()
The watch()
method lets us easily observe a State for changes.
Thereby is the provided callback
function fired on every State value
mutation.
Such mutation occurs when we, for example, update the State value
from 'jeff' to 'hans'.
const response = MY_STATE.watch((value, key) => {
console.log(value); // Returns current State Value
console.log(key); // Key of Watcher ("Aj2pB")
});
console.log(response); // "Aj2pB" (Random generated Key to identify the watcher callback)
We recommend giving each watcher
callback a unique key
to correctly identify it later.
const something = MY_STATE.watch("myKey", (value, key) => {
// do something
});
console.log(response); // State Instance it was called on
Such identification is, for example, essential to clean up the watcher callback later.
❓ When cleanup
We should clean up a watcher callback when it is no longer in use. In a UI-Component, that is the case whenever the Component unmounts. If we forget to clean up many of these watcher callbacks, memory leaks may occur.
MY_STATE.removeWatcher(cleanupKey);
🚀 useWatcher
In a React environment we can use the useWatcher()
hook to create a watcher callback
without worrying about cleaning it up after the UI-Component has unmounted.
export const MyComponent = () => {
useWatcher(MY_STATE, (value) => {
// do something
});
return <div></div>;
}
📭 Props
Prop | Type | Default | Description | Required |
---|---|---|---|---|
key | string | number | undefined | Key/Name of Watcher Callback | No |
callback | (value: ValueType) => void | undefined | Callback function that is called on each State value change | Yes |
📄 Return
State | string
removeWatcher()
Removes watcher callback at the given watcherKey
from the State.
MY_STATE.removeWatcher("myKey");
📭 Props
Prop | Type | Default | Required |
---|---|---|---|
watcherKey | number | string | undefined | Yes |
📄 Return
State
Returns the State it was called on.
hasWatcher()
warning
onInaugurated()
A watcher callback that destroys itself after invoking.
MY_STATE.onInaugurated((value) => {
// do something
});
Therefore, this callback is called only once shortly after the initiation of the State.
📭 Props
Prop | Type | Default | Required |
---|---|---|---|
callback | (value: ValueType) => void | undefined | Yes |
📄 Return
State
Returns the State it was called on.
persist()
Preserves the State value
in the appropriate local Storage for the current environment.
MY_STATE.perist({key: "myStorageKey"});
🤓 Learn more
If you want to find out more about persisting Instances like States, checkout the Persisting Data Section.
📭 Props
Prop | Type | Default | Description | Required |
---|---|---|---|---|
config | StatePersistentConfig | {} | Configuration | No |
📄 Return
State
Returns the State it was called on.
onLoad()
Registers a callback function that is called whenever the persisted State value
is loaded into the State.
MY_STATE.onLoad((success) => {
console.log(`Value '${MY_STATE.value}' got loaded into the Collection! Success? ${success}`)
});
For example, we can use this information to display a loading indicator
until the persisted value
got loaded.
📭 Props
Prop | Type | Default | Required |
---|---|---|---|
callback | (success: boolean) => void | undefined | Yes |
📄 Return
State
Returns the State it was called on.
exists()
Checks whether the State exists.
const MY_STATE = createState("hi");
MY_STATE.exists; // Returns 'true'
Criteria for an existing State are:
- State is no
placeholder
computeExists
method returnstrue
📄 Return
boolean
computeExists()
Updates the method used to compute the existence of the State.
It will be retrieved on each exists()
method call to determine whether the State exists.
MY_STATE.computeExists((value) => value !== undefined && value !== 'jeff');
The default computeExists()
method checks if the State is null
or undefined
.
(value) => {
return value != null;
};
📭 Props
Prop | Type | Default | Required |
---|---|---|---|
method | (value: ValueType) => boolean | undefined | Yes |
📄 Return
State
Returns the State it was called on.
is()
Whether the State value is equal
to the provided value.
Equivalent to ===
with the difference that it looks at the value
and not on the reference in the case of objects.
const MY_STATE = createState("hi");
MY_STATE.is("bye"); // Returns 'false'
MY_STATE.is("hi"); // Returns 'true'
📭 Props
Prop | Type | Default | Required |
---|---|---|---|
value | ValueType (any) | undefined | Yes |
📄 Return
boolean
isNot()
Whether the State value isn't equal
to the provided value.
Equivalent to !==
with the difference that it looks at the value
and not on the reference in the case of objects.
const MY_STATE = createState("hi");
MY_STATE.isNot("bye"); // Returns 'true'
MY_STATE.isNot("hi"); // Returns 'false'
📭 Props
Prop | Type | Default | Required |
---|---|---|---|
value | ValueType (any) | undefined | Yes |
📄 Return
boolean
invert()
Inverts the current State value.
const MY_STATE = createState(true);
MY_STATE.invert(); // State Value is 'false'
Some more examples are:
// 'jeff' -> 'ffej'
// true -> false
// [1, 2, 3] -> [3, 2, 1]
// 10 -> -10
📄 Return
State
Returns the State it was called on.
computeValue()
Creates method that is called on each State value mutation to adjust the value before it is applied to the State.
const MY_STATE = createState("Jeff").compute((value) => `Hello '${value}'`);
MY_STATE.value; // Returns "Hello 'Jeff'"
MY_STATE.set("Frank");
MY_STATE.value; // Returns "Hello 'Frank'"
⚙️ Computed vs computeValue()
The computeValue()
method is thought to make small adjustments to the State value before it is applied to the State.
The Computed Class on the other hand computes its value based on several Agile Sub Instances
like States, Collections, ..
const isAuthenticated = createComputed(() => {
return authToken.exists && user.exists && !timedout.value;
});
It recomputes its value whenever a dependency (like the authToken
) mutates.
📭 Props
Prop | Type | Default | Required |
---|---|---|---|
method | (value: ValueType) => ValueType | undefined | Yes |
📄 Return
State
Returns the State it was called on.
addSideEffect()
warning
This method is mainly thought for the internal use.
Creates a callback
function that is executed in the runtime
as a side effect of State changes.
For example, it is called when the State value changes from 'jeff' to 'hans'.
MY_STATE.addSideEffect('mySideEffect', (state, config) => {
// sideEffect callback
});
✨ Multiple sideEffects
Each State can have multiple sideEffects
with different weights
.
MY_STATE.addSideEffect('mySideEffect', (state, config) => {
// sideEffect callback
}, {weigth: 10});
The weight
determines in which order the sideEffects
are executed,
since some sideEffects
have to be performed before others.
The higher the weigth
, the earlier the sideEffect
callback will be called.
👾 Example
For example, a persisted Group has two sideEffects
.
rebuildGroup
with a weight of 10: Rebuilds the Groupoutput
.rebuildStateStorageValue
with a weight of 0: Updates the persisted Groupvalue
in the appropriate local Storage.
📭 Props
Prop | Type | Default | Description | Required |
---|---|---|---|---|
key | string | number | undefined | Key/Name of sideEffect callback | Yes |
callback | (instance: Instance, properties?: object) => void | undefined | Callback Function that is called on each State mutation | Yes |
config | AddSideEffectConfigInterface | {} | Configuration | No |
📄 Return
State
Returns the State it was called on.
removeSideEffect()
warning
This method is mainly thought for the internal use.
Removes sideEffect at the given sideEffectKey
from the State.
MY_STATE.removeSideEffect("myKey");
📭 Props
Prop | Type | Default | Required |
---|---|---|---|
sideEffectKey | number | string | undefined | Yes |
📄 Return
State
Returns the State it was called on.
hasSideEffect()
warning
This method is mainly thought for the internal use.
Checks if a sideEffect exists at the given sideEffectKey
in the State.
MY_STATE.addSideEffect("myKey", (value) => {
// do something
});
MY_STATE.hasSideEffect("myKey"); // Returns 'true'
MY_STATE.hasSideEffect("unknownKey"); // Returns 'false'
📭 Props
Prop | Type | Default | Required |
---|---|---|---|
sideEffectKey | number | string | undefined | Yes |
📄 Return
boolean