Reactivity is the framework's capability to automatically update parts of the user interface when underlying application state changes.
Nijor features a highly performant and intuitive reactivity model. Reactive variables are declared and managed using a special prefix, completely bypassing the need for standard JavaScript variable declarations like let or const.
You declare a reactive variable using the prefix $. inside your <script> block. Once declared, you can render this state in your template using curly brace interpolation {$.variableName}.
<body>
<h1>Counter : {$.count}</h1>
</body>
<script>
$.count = 0;
</script>
Whenever the value of $.count changes, Nijor pinpoints the text node and updates the DOM directly.
To update reactive state, assign a new value to the reactive variable.
Important Event Signature Rule: Any event handler function in your <script> that modifies reactive state must accept the reactivity context $ as its last parameter. When calling the event handler from the template, you do not pass the $ argument explicitly; Nijor's compiler injects it automatically at runtime.
<body>
<h1>Counter : {$.count}</h1>
<button on:click="increment()">Increase</button>
<button on:click="decrement()">Decrease</button>
</body>
<script>
$.count = 0;
export function increment($) {
$.count++;
}
export function decrement($) {
$.count--;
}
</script>
Derived reactive variables are values that depend entirely on other reactive state. Nijor automatically tracks these dependencies and recalculates the derived variable whenever its parent state changes.
You declare derived state using a JavaScript label with a colon prefix _ : followed by the assignment:
$.count = 0;
_ : $.double = $.count * 2;
In the example below, $.double depends on $.count. Whenever $.count increases or decreases, $.double is recalculated and any bound DOM nodes automatically refresh.
<body>
<h2>Original Count : {$.count}</h2>
<h2>Doubled Value : {$.double}</h2>
<button on:click="increment()">Add 1</button>
</body>
<script>
$.count = 0;
_ : $.double = $.count * 2;
export function increment($) {
$.count++;
}
</script>
If you need to access raw DOM nodes directly (e.g., to focus an input, trigger video playback, or read a form element's current property), use the n:ref attribute.
When applied, Nijor registers the DOM element directly onto your reactivity context as $.varName:
<body>
<input type="text" n:ref="{$.username}" placeholder="Enter name">
<button on:click="showValue()">Show Value</button>
</body>
<script>
export function showValue($) {
console.log($.username.value); // Access the native DOM node
}
</script>
This works seamlessly with other elements, such as dropdown selects:
<body>
<select n:ref="{$.theme}">
<option value="light">Light Mode</option>
<option value="dark">Dark Mode</option>
</select>
<button on:click="printTheme()">Print Theme</button>
</body>
<script>
export function printTheme($) {
console.log($.theme.value);
}
</script>
To bind a user input's value directly to a reactive state variable in real time, use the n:bind attribute. This sets up a one-way sync between your DOM element and your reactive state :
It is fully supported on input tags, textarea elements, and any container containing the contenteditable="true" property.
<body>
<h1>নমস্কাৰ {$.name || "Stranger"}!</h1>
<input n:bind="{$.name}" placeholder="Type your name...">
</body>
As you type inside the input, $.name is updated dynamically, causing the welcome header to immediately reflect the typed text.
<body>
<textarea n:bind="{$.message}"></textarea>
<p>Characters : {$.message.length}</p>
</body>
<body>
<div contenteditable="true" n:bind="{$.text}"></div>
<p>Raw text : {$.text}</p>
</body>
The global prefix $ is reserved exclusively for Nijor's reactivity system. Never re-declare or override the $ variable manually inside your components.
Always ensure your state-modifying functions receive the $ argument in their function signature.
Reactivity variables do not require initialization using let, var, or const; simply write $.myVar = value directly inside your component scripts.