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
runtimequeue - Execute State Job
- Execute
sideEffectslike 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
valueto 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 computeExistsmethod 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.
rebuildGroupwith a weight of 10: Rebuilds the Groupoutput.rebuildStateStorageValuewith a weight of 0: Updates the persisted Groupvaluein 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