Skip to main content

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

PropTypeDefaultRequired
valuestring | number | undefinedundefinedYes

📄 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

  1. Ingest State Observer into the runtime (Observer is like an interface to runtime)
  2. Create State Job and add it to the runtime queue
  3. Execute State Job
  4. Execute sideEffects like permanently storing the State in a Storage
  5. Update all Subscribers of the State Observer (-> trigger rerender on subscribed Components)

📭 Props

PropTypeDefaultDescriptionRequired
valueValueType = anyundefinedValue that will be assigned to the State nextYes
configStateIngestConfig{}ConfigurationNo

📄 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

PropTypeDefaultDescriptionRequired
configStateIngestConfig{}ConfigurationNo

📄 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

PropTypeDefaultDescriptionRequired
configStateIngestConfig{}ConfigurationNo

📄 Return

State

Returns the State it was called on.




reset()

Resets the State. A reset includes:

  • setting the State value to it's initialValue
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

PropTypeDefaultDescriptionRequired
configStateIngestConfig{}ConfigurationNo

📄 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

PropTypeDefaultDescriptionRequired
targetWithChangesObjectundefinedObject merged into the current State valueYes
configPatchConfig{}ConfigurationNo

📄 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

PropTypeDefaultDescriptionRequired
keystring | numberundefinedKey/Name of Watcher CallbackNo
callback(value: ValueType) => voidundefinedCallback function that is called on each State value changeYes

📄 Return

State | string



removeWatcher()

Removes watcher callback at the given watcherKey from the State.

MY_STATE.removeWatcher("myKey");

📭 Props

PropTypeDefaultRequired
watcherKeynumber | stringundefinedYes

📄 Return

State

Returns the State it was called on.




hasWatcher()

🔥warning

The hasWatcher() method has been deprecated in the latest version ^0.2.0 and is no longer available!

Why?

Reducing core package size.

Alternative?

MY_STATE.hasSideEffect('watcherKey');



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

PropTypeDefaultRequired
callback(value: ValueType) => voidundefinedYes

📄 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

PropTypeDefaultDescriptionRequired
configStatePersistentConfig{}ConfigurationNo

📄 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

PropTypeDefaultRequired
callback(success: boolean) => voidundefinedYes

📄 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:

📄 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

PropTypeDefaultRequired
method(value: ValueType) => booleanundefinedYes

📄 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

PropTypeDefaultRequired
valueValueType (any)undefinedYes

📄 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

PropTypeDefaultRequired
valueValueType (any)undefinedYes

📄 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

PropTypeDefaultRequired
method(value: ValueType) => ValueTypeundefinedYes

📄 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.

Example sideEffect

  • rebuildGroup with a weight of 10: Rebuilds the Group output.
  • rebuildStateStorageValue with a weight of 0: Updates the persisted Group value in the appropriate local Storage.

📭 Props

PropTypeDefaultDescriptionRequired
keystring | numberundefinedKey/Name of sideEffect callbackYes
callback(instance: Instance, properties?: object) => voidundefinedCallback Function that is called on each State mutationYes
configAddSideEffectConfigInterface{}ConfigurationNo

📄 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

PropTypeDefaultRequired
sideEffectKeynumber | stringundefinedYes

📄 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

PropTypeDefaultRequired
sideEffectKeynumber | stringundefinedYes

📄 Return

boolean