Skip to main content

Interfaces

❗️info

This Section might be useless to you without any context. As the name suggests, it's all about typescript interfaces of AgileTs. These interfaces are outsourced for a better overview, maintainability, and reusability. You might get redirected to parts of the Interface Section from other documentation to learn more about specific Interfaces.

StateIngestConfig

The StateIngestConfigInterface is used as configuration object in functions like set() or undo(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface StateIngestConfigInterface
extends StateRuntimeJobConfigInterface,
IngestConfigInterface {
key?: RuntimeJobKey;
}

Note: The StateIngestConfigInterface extends some other Interfaces:


key

The key/name of the Job that is created and ingested into the runtime.

MY_STATE.set('hello there', {key: 'jeff'});

Such key can be very useful during debug sessions in order to analyse when which Job ran through the runtime.

// Agile Debug: Created Job 'jeff', Job('jeff')
// Agile Debug: Completed Job 'jeff', Job('jeff')
// Agile Debug: Updated/Rerendered Subscriptions, [SubscriptionContainer, ..]
TypeDefaultRequired
string \| numberundefinedNo



StateRuntimeJobConfig

The StateRuntimeJobConfigInterface is used as configuration object in functions like replace() or select(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface StateRuntimeJobConfigInterface
extends RuntimeJobConfigInterface {
overwrite?: boolean;
storage?: boolean;
}

Note: The StateRuntimeJobConfigInterface extends some other Interfaces:


overwrite

If true, the whole State is overwritten with the newly assigned value.

MY_STATE.set("finalValue", {overwrite: true});
MY_STATE.value; // Returns 'finalValue'
MY_STATE.previousStateValue; // Returns 'finalValue'
MY_STATE.initialStateValue; // Returns 'finalValue'

During the overwrite process, the following properties are overwritten:

  • value
  • previousStateValue
  • initalStateValue
  • isPlaceholder
TypeDefaultRequired
booleanfalseNo

storage

Whether to apply the State value changes to the corresponding external Storage/s.

const MY_STATE = createState('jeff').persist('storageKey');
// Storage at 'storageKey': 'jeff'
MY_STATE.set("hans", {storage: true});
// Storage at 'storageKey': 'hans'
MY_STATE.set("dieter", {storage: false});
// Storage at 'storageKey': 'hans'

Be aware that this is only relevant, if the State is persisted. We can use the isPersisted property to check whether a state is persisted.

MY_STATE.isPersisted;
TypeDefaultRequired
booleantrueNo



RuntimeJobConfigInterface

The RuntimeJobConfigInterface is used in the creation and configuration of a Runtime Job. Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface RuntimeJobConfigInterface {
background?: boolean;
sideEffects?: SideEffectConfigInterface;
force?: boolean;
numberOfTriesToUpdate?: number | null;
}

background

When true, the Job is executed in the background and won't cause any rerender on Components that have subscribed the Agile Sub Instance represented by the Job.

// Causes rerender on Components
MY_STATE.set("myNewValue2");

// Doesn't cause rerender on Components
MY_STATE.set("myNewValue3", {background: true});
TypeDefaultRequired
booleanfalseNo

sideEffects

Specifies whether the side effects of the Job should be executed.

// Executes sideEffects
MY_STATE.set("myNewValue2");

// Doesn't execute sideEffects
MY_STATE.set("myNewValue3", {sideEffects: false});

During a side effect, several essential tasks are done. These include, for example, rebuilding the Group output of a Group or updating the persisted State value in the corresponding external Storage.

TypeDefaultRequired
booleantrueNo

force

When set to true, the Job is forced through the runtime no matter what happens.

const MY_STATE = createState('myValue');

// Won't be executed by the runtime because the State value hasn't changed
MY_STATE.set('myValue');

// Will be executed by the runtime, although the State value hasn't changed
MY_STATE.set('myValue', { force: true });
TypeDefaultRequired
booleanfalseNo

numberOfTriesToUpdate

How often the runtime should try to update not ready SubscriptionContainers of the Job. If the update tries count exceeds the numberOfTriesToUpdate count, the Job will be entirely removed from the runtime. This has the advantage that an overflow of the runtime is avoided. If numberOfTriesToUpdate is null the runtime tries to update the not ready Job subscriptionContainers until they are ready.

TypeDefaultRequired
number \| null3No



IngestConfigInterface

The IngestConfigInterface is used as a configuration object to configure the ingest process of Jobs into the runtime. Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface IngestConfigInterface {
perform?: boolean;
}

perform

Whether the ingested Job should be executed immediately by the runtime or should first be inserted into a queue and performed when it is its turn.

TypeDefaultRequired
booleantrueNo



PatchConfig

The PatchConfigInterface is used as configuration object in functions like patch(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface PatchConfigInterface extends StateIngestConfigInterface {
addNewProperties?: boolean;
}

Note: The PatchConfigInterface extends some other Interfaces:


addNewProperties

If true, new properties are added to the State value, although they might not yet be present there.

const MY_STATE = createState({id: 1, name: "frank"});
MY_STATE.patch({location: "Germany"}, {addNewProperties: false});
MY_STATE.value; // Returns {id: 1, name: "frank"}
MY_STATE.patch({location: "Germany"}, {addNewProperties: true});
MY_STATE.value; // Returns {id: 1, name: "frank", location: "Germany"}
TypeDefaultRequired
booleantrueNo



StatePersistentConfig

The StatePersistentConfigInterface is used as configuration object in functions like persist(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface StatePersistentConfigInterface {
key?: string | number;
loadValue?: boolean;
storageKeys?: StorageKey[];
onMigrate?: (value: any) => ValueType;
onSave?: (value: ValueType) => any;
}

loadValue

When true, the created Persistent automatically loads the value stored in the corresponding external Storage into the State. Or, if the State isn't persisted yet, it stores the State value in the corresponding external Storage. Be aware that if we don't allow the Persistent to load/store the value, we have to do it ourselves.

myState.persist({
loadValue: false,
});

if (myState.persistent?.ready) {
await myState.persistent?.initialLoading();
myState.isPersisted = true;
}

Loading the value manually has one advantage. It allows us to await the asynchronous load/store process. If you only need to await the loading process we recommend using the onLoad() method.

TypeDefaultRequired
booleantrueNo

storageKeys

Specifies the Storage/s the State value should be persisted in.

MY_STATE.persist(); // Stores value in default Storage
MY_STATE.persist({storageKeys: ['myCustomStorrage']}); // Stores value in 'myCustomStorrage'

If no specific Storage defined, the State value will be stored/persisted in the default Storage.

TypeDefaultRequired
Array<string \| number>'defaultStorage'No



GroupConfig

The GroupConfigInterface is used in the creation and configuration of the Group Class. Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface GroupConfigInterface {
key?: GroupKey;
isPlaceholder?: boolean;
}

key

The optional property key/name should be a unique string/number to identify the Group later.

MY_COLLECTION.createGroup([1, 2, 3], {
key: "myKey"
});

We recommend giving each Group a unique key since it has only advantages:

  • helps us during debug sessions
  • makes it easier to identify the Group
  • no need for separate persist Key
TypeDefaultRequired
string \| nameundefinedNo

isPlaceholder

Defines whether the Group is a placeholder.

const MY_GROUP = createGroup([1, 2, 3], {
isPlaceholder: true
});

MY_GROUP.exists(); // false

Groups are placeholder when AgileTs needs to hold a reference to them, even though they aren't instantiated yet. This can be the case if we use the getGroupWithReference() method, which returns a placeholder Group if the Group we are looking for doesn't exist yet.

const myGroup = useAgile(MY_COLLECTION.getGroupWithReference("group1")); // Causes rerender if Group got created
const myGroup2 = useAgile(MY_COLLECTION.getGroup("group2")); // Doesn't causes rerender if Group got created

This reference is essential to rerender the Component, whenever the Group got instantiated.

TypeDefaultRequired
booleanfalseNo



SelectorConfig

The SelectorConfigInterface is used in the creation and configuration of the Selector Class. Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface SelectorConfigInterface {
key?: SelectorKey;
isPlaceholder?: boolean;
}

key

The optional property key/name should be a unique string/number to identify the Selector later.

MY_COLLECTION.createSelector(1, {
key: "myKey"
});

We recommend giving each Selector a unique key since it has only advantages:

  • helps us during debug sessions
  • makes it easier to identify the Selector
  • no need for separate persist Key
TypeDefaultRequired
string \| nameundefinedNo

isPlaceholder

Defines whether the Selector is a placeholder.

const MY_SELECTOR = MY_COLLECTION.createSelector(1, {
isPlaceholder: true
});

MY_SELECTOR.exists(); // false

Selectors are placeholder when AgileTs needs to hold a reference to them, even though they aren't instantiated yet. This can be the case if we use the getSelectorWithReference() method, which returns a placeholder Selector if the Selector we are looking for doesn't exist yet.

const mySeleector = useAgile(MY_COLLECTION.getSelectorWithReference("selector1")); // Causes rerender if Selector got created
const mySeleector2 = useAgile(MY_COLLECTION.getSelector("selector2")); // Doesn't causes rerender if Selector got created

This reference is essential to rerender the Component, whenever the Selector got instantiated.

TypeDefaultRequired
booleanfalseNo



CollectConfig

The CollectConfigInterface is used as configuration object in functions like collect(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface CollectConfigInterface<DataType = any> {
patch?: boolean;
method?: 'push' | 'unshift';
forEachItem?: (data: DataType, key: ItemKey, index: number) => void;
background?: boolean;
select?: boolean;
}

patch

❗️info

The patch property is only relevant to us if we collect a data object with an already existing primaryKey in order to update the Item data at that primaryKey.

If true, the passed data object is merged into the found Item data instead of overwriting it entirely.

const MY_COLLECTION = createCollection({
initialData: [{id: 1, name: 'frank', age: 10}]
});

MY_COLLECTION.collect({id: 1, name: 'hans'}, [], {patch: true});
MY_COLLECTION.getItemValue(1); // Returns '{id: 1, name: 'hans', age: 10}'

MY_COLLECTION.collect({id: 1, name: 'jeff'}, [], {patch: false});
MY_COLLECTION.getItemValue(1); // Returns '{id: 1, name: 'frank'}'

An alternative to this way of updating already existing Item data is the update() method.

TypeDefaultRequired
booleanfalseNo

method

Specifies the way of adding the collected data primaryKey/s to the defined Group/s.

push

The primaryKey is added to the end of the Group value array.

MY_COLLECTION.collect({id: 1, name: "jeff"}, [], {method: 'push'});
MY_COLLECTION.getGroup(MY_COLLECTION.config.defaultGroupKey).value; // Returns [5, 6, 0, 1]
unshift

The primaryKey is added to the beginning of the Group value array.

MY_COLLECTION.collect({id: 8, name: "jeff"}, [], {method: 'unshift'});
MY_COLLECTION.getGroup(MY_COLLECTION.config.defaultGroupKey).value; // Returns [8, 5, 6, 0, 1]
TypeDefaultRequired
push' \| 'unshift''push'No

forEachItem

Callback that is called for each collected data object.

MY_COLLECTION.collect([
{id: 1, name: "jeff"},
{id: 8, name: "frank"}],
[],
{forEachItem: (data, key, index) => {
// Is called with 'data: {id: 1, name: "jeff"}, key: 1, index: 0'
// and
// Is called with 'data: {id: 2, name: "frank"}, key: 8, index: 1'
}
});
TypeDefaultRequired
(data: DataType, key: ItemKey, index: number) => voidundefinedNo

background

When true, the data object/s are collected in background and won't cause any rerender on Components that have subscribed the Collection.

  // Causes rerender on Components
MY_COLLECTION.collect({id: 1, name: "jeff"});

// Doesn't cause rerender on Components
MY_COLLECTION.collect({id: 1, name: "jeff"}, {background: true});
TypeDefaultRequired
booleanfalseNo

select

If true, a Selector is created for each collected data object.

MY_COLLECTION.collect({id: 1, name: "jeff"}, {select: true});
MY_COLLECTION.getSelector(1); // Returns Selector at '1'

These created Selectors can be identified with the same key used as primaryKey in the collected data object.

TypeDefaultRequired
booleanfalseNo



UpdateConfig

The UpdateConfigInterface is used as configuration object in functions like update(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface UpdateConfigInterface {
patch?: boolean | { addNewProperties?: boolean };
background?: boolean;
}

patch

If false, the passed data object overwrites the entire found Item data instead of merging it into the Item data.

MY_COLLECTION.collect({id: 1, name: "jeff"});
MY_COLLECTION.update(1, {name: "hans"}, {patch: true});
MY_COLLECTION.getItemValue(1); // Returns '{id: 1, name: "hans"}'
MY_COLLECTION.update(1, {name: "frank"}, {patch: false});
MY_COLLECTION.getItemValue(1); // Returns '{name: "frank"}'

Keep in mind that if we decide to overwrite the entire Item data object, we have to redefine the primaryKey in the given data object. Otherwise, the primary Key gets missing, which can lead to problems.

TypeDefaultRequired
booleantrueNo

background

When true, the Item data object is updated in background and won't cause any rerender on Components that have subscribed the Item or Collection.

// Causes rerender on Components
MY_COLLECTION.update(1, {name: "jeff"});

// Doesn't cause rerender on Components
MY_COLLECTION.update(1, {name: "frank"}, {background: true});
TypeDefaultRequired
booleanfalseNo



HasConfig

The HasConfigInterface is used as configuration object in functions like hasGroup() or hasSelector(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface HasConfigInterface {
notExisting?: boolean;
}

notExisting

When true, also not officially existing Instances (like placeholder) can be found.

// Returns placeholder Group
MY_COLLECTION.hasGroup('myPlaceholderGroup', {notExisting: true});

// Returns undefined
MY_COLLECTION.hasGroup('myPlaceholderGroup');
TypeDefaultRequired
booleanfalseNo



AddSideEffectConfig

The AddSideEffectConfigInterface is used as configuration object in functions like addSideEffect(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface AddSideEffectConfigInterface {
weight?: number;
}

weight

Defines the weight of the sideEffect and thus when it is executed.

MY_STATE.addSideEffect('mySideEffect', (state, config) => {
// sideEffect callback
}, {weigth: 10});

The higher the weight, the earlier the sideEffect is performed.

TypeDefaultRequired
number10No



GroupAddConfig

The GroupAddConfigInterface is used as configuration object in functions like put() or add(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface GroupAddConfig extends StateIngestConfigInterface {
method?: 'unshift' | 'push';
overwrite?: boolean;
}

Note: The GroupAddConfig extends some other Interfaces:


method

Specifies the way of adding the collected data primaryKey/s to the defined Group/s.

push

The primaryKey is added to the end of the Group value array.

MY_COLLECTION.collect({id: 1, name: "jeff"}, [], {method: 'push'});
MY_COLLECTION.getGroup(MY_COLLECTION.config.defaultGroupKey).value; // Returns [5, 6, 0, 1]
unshift

The primaryKey is added to the beginning of the Group value array.

MY_COLLECTION.collect({id: 8, name: "jeff"}, [], {method: 'unshift'});
MY_COLLECTION.getGroup(MY_COLLECTION.config.defaultGroupKey).value; // Returns [8, 5, 6, 0, 1]
TypeDefaultRequired
push' \| 'unshift''push'No

overwrite

If true, the position of the already existing itemKey gets overwritten with the new position of the newly added same itemKey.

const MY_GROUP = MY_COLLECTION.createGroup('group1', [1, 2, 5, 6]);
MY_GROUP.add(2, {overwrite: true}); // Group value is '[1, 5, 6, 2]'
MY_GROUP.add(5); // Group value is '[1, 5, 6, 2]'
TypeDefaultRequired
booleanfalseNo



UpdateItemKeyConfig

The UpdateItemKeyConfigInterface is used as configuration object in functions like updateItemKey(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface UpdateItemKeyConfigInterface {
background?: boolean;
}

background

When true, the itemKey is updated in background and won't cause any rerender on Components that have subscribed the Item or Collection.

// Causes rerender on Components
MY_COLLECTION.updateItemKey([1, 3]);

// Doesn't cause rerender on Components
MY_COLLECTION.updateItemKey([1, 3], {background: true});
TypeDefaultRequired
booleanfalseNo



ComputeConfig

The ComputeConfigInterface is used as configuration object in functions like compute(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface ComputeConfigInterface {
autodetect?: boolean;
}

autodetect

Tells the Computed Class to automatically detect the dependencies (Agile Sub Instances used in the computeFunction().

MY_COMPUTED.computeFunction = () => MY_NAME.value + MY_AGE.value;
MY_COMPUTED.recompute({autodetect: false});
MY_COMPUTED.deps; // Returns '[]'
MY_COMPUTED.recompute({autodetect: true});
MY_COMPUTED.deps; // Returns '[Obserrver(MY_NAME), Observer(MY_AGE)]'
TypeDefaultRequired
booleantrueNo



RecomputeConfig

The RecomputeConfigInterface is used as configuration object in functions like recompute(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface RecomputeConfigInterface
extends StateIngestConfigInterface,
ComputeConfigInterface {}

Note: The RecomputeConfig extends some other Interfaces:




UpdateComputeFunctionConfig

The UpdateComputeFunctionConfigInterface is used as configuration object in functions like updateComputeFunction(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

export interface UpdateComputeFunctionConfigInterface
extends RecomputeConfigInterface {
overwriteDeps?: boolean;
}

Note: The RecomputeConfig extends some other Interfaces:


overwriteDeps

Whether the newly defined hard-coded dependencies are merged into the existing ones or overwrite them entirely.

MY_COMPUTED.deps; // // Returns '[Obserrver(MY_NAME), Observer(MY_AGE)]'
MY_COMPUTED.updateComputeFunction(() => {}, [MY_LOCATION], {overwriteDeps: false});
MY_COMPUTED.deps; // // Returns '[Obserrver(MY_NAME), Observer(MY_AGE), Observer(MY_LOCATION)]'
MY_COMPUTED.updateComputeFunction(() => {}, [MY_LOCATION], {overwriteDeps: true});
MY_COMPUTED.deps; // // Returns '[Observer(MY_LOCATION)]'
TypeDefaultRequired
booleantrueNo



AgileHookConfigInterface

The AgileHookConfigInterface is used as configuration object in functions like useAgile(). Here is a Typescript Interface for quick reference. However, each property is explained in more detail below.

interface AgileHookConfigInterface {
key?: SubscriptionContainerKeyType;
agileInstance?: Agile;
proxyBased?: boolean;
selector?: SelectorMethodType;
componentId?: ComponentIdType;
observerType?: string;
deps?: any[];
}

key

The key/name of the SubscriptionContainer that is created and added to the Observers.

useAgile(MY_STATE, {key: 'jeff'});

Such key can be very useful during debug sessions in order to analyse when which SubscriptionContainer triggered a rerender on a Component.

// Agile Debug: Registered Callback/Component based Subscription 'jeff', SubscriptionContainer('jeff')
// Agile Debug: Updated/Rerendered Subscriptions, [SubscriptionContainer('jeff'), ..]
// Agile Debug: Unregistered Callback/Component based Subscription 'jeff', SubscriptionContainer('jeff')
TypeDefaultRequired
string \| numberundefinedNo

agileInstance

The Agile Instance to which the created SubscriptionContainer belongs to. However, since each Observer has an instance to the Agile Instance, useAgile() can automatically derive the Agile Instance from that.

TypeDefaultRequired
Agile InstanceundefinedNo

proxyBased

🔥warning

Requires an additional package called @agile-ts/proxytree!

Whether to wrap a Proxy around the bound Agile Instance value object, to automatically constrain the way the selected Agile Instance is compared to determine whether the Component needs to be re-rendered based on the object's used properties.

useProxy(MY_STATE);
// equal to
useAgile(MY_STATE, {proxyBased: true});
TypeDefaultRequired
booleanfalseNo

selector

🔥warning

Note that setting this property can destroy the useAgile type. -> should only be used internal!

useSelector(MY_STATE, (v.name) => v.name);
// equal to
useAgile(MY_STATE, {selector: (v.name) => v.name});

Equality comparison function that allows you to customize the way the selected Agile Instance is compared to determine whether the Component needs to be re-rendered.

TypeDefaultRequired
SelectorMethodTypeundefinedNo

componentId

Key/Name identifier of the UI-Component the Subscription Container is bound to.

useAgile(MY_STATE, {componentId: 'User.tsx'});

In future re-render events with the same componentId are batched, in addition to batching re-render events based on the SubscriptionContainer.

TypeDefaultRequired
string\|numberundefinedNo

observerType

🔥warning

Note that setting this property can destroy the useAgile type. -> should only be used internal!

useOutput(MY_STATE);
// equal to
useAgile(MY_STATE, {observerType: 'output'});

useValue(MY_STATE);
// equal to
useAgile(MY_STATE, {observerType: 'value'});

What type of Observer to be bound to the UI-Component.

TypeDefaultRequired
stringfalseNo

deps

Dependencies that determine, in addition to unmounting and remounting the React-Component, when the specified Agile Sub Instances should be re-subscribed to the React-Component.

Related to github issue.

TypeDefaultRequired
any[][]No