Core Concepts

Create your first expression

RS-X has been designed to make reactivity simple.

Quick intro

RS-X has been designed to make reactivity simple. You define your model, bind an expression to it, and subscribe to the changed event to react to changes.

It is nothing more than that. The expression makes only the model parts it uses reactive.

RS-X handles the complexity for you: async operations and different data types are handled by the runtime.

Example

Let's go through the basic steps with a simple example.

import { InjectionContainer } from '@rs-x/core';
import { rsx, RsXExpressionParserModule } from '@rs-x/expression-parser';
import { interval, map, startWith } from 'rxjs';

await InjectionContainer.load(RsXExpressionParserModule);

const model = {
  a: 10,
  b: interval(2000).pipe(
    map(() => Math.floor(Math.random() * 100)),
    startWith(20),
  ),
};
const sum = rsx<number>('a + b')(model);

const subscription = sum.changed.subscribe(() => {
  console.log('changed:', sum.value);
});

subscription.unsubscribe();
sum.dispose();

What this code does

  • Declare the expression: rsx('a + b')
  • Bind it to the model: (model)
  • Subscribe to changes: sum.changed.subscribe(...)
  • Observable source emits new values every 2s: interval(...).pipe(...)
  • Read the new expression value in the callback: sum.value
  • Cleanup when done: subscription.unsubscribe(); sum.dispose();

When to use options

In most cases you keep using: rsx('a + b')(model) . Add options only when you need build-time optimization behavior.

OptionUse it whenWhere it is used
leafIndexWatchRuleYou need to control which property changes on the expression's resolved value trigger re-evaluationrsx('expr')(model, watchRule)
preparseParse this expression at compile time so runtime parser work is skippedSecond argument of the declaration call: rsx(expression, { preparse })
lazyLoad this expression cache entry only when it is first usedSecond argument of the declaration call: rsx(expression, { lazy })
compiledEnable/disable compiled-plan generation for this expression site (default true)Second argument of the declaration call: rsx(expression, { compiled })

How to use them in code:

// Declaration options (compiler/AOT hints)
const bindSum = rsx<number>('a + b', {
  preparse: true,
  lazy: false,
  compiled: true,
});

// Runtime binding
const sum = bindSum(model);