# Reactivity APIs Lune's reactivity comes from `@lune-js/core`, a focused port of `@vue/reactivity` built on [Alien Signals](https://github.com/stackblitz/alien-signals). `lune-js` re-exports it, so you never need to install it separately: `reactive()`, `readonly()`, `shallowReactive()`, `shallowReadonly()` and `effect()` are the primitives you build with. ## Usage When using the CDN build, these APIs are available on the global `Lune` object. ```html ``` When using the ES module build, you can import them from `lune-js`. ```js import { effect, nextTick, reactive, readonly, shallowReactive, shallowReadonly } from "lune-js"; ``` ## API Reference ### `reactive(object)` Returns a reactive proxy of the given object. This is typically used for defining the initial state of your application. ```js const state = reactive({ count: 0 }); ``` Nested objects and arrays are proxied on access, so mutations at any depth are tracked. ### `readonly(object)` Returns a deeply read-only proxy of the given object. Writes are rejected with a development warning, which makes it a good wrapper for state you want to share but not let templates mutate. ```js const state = reactive({ count: 0 }); const frozen = readonly(state); ``` ### `shallowReactive(object)` / `shallowReadonly(object)` The same as `reactive()` and `readonly()`, except only top-level properties are tracked. Nested objects are handed back untouched, which is useful for holding large or foreign objects (a third-party instance, a big payload) without proxying their internals. ### `effect(fn)` Runs a function immediately while reactively tracking its dependencies and re-runs it whenever the dependencies change. It returns the effect runner, whose `.effect` handle exposes `stop()` when you need to tear the effect down manually. ```js const state = reactive({ count: 0 }); effect(() => console.log(state.count)); // prints 0 state.count++; // prints 1 ``` Effects created by directives are stopped for you when the element is removed or `app.unmount()` runs. Effects you create yourself are not tied to any element, so stop them yourself if they should not outlive the page. ### `nextTick(fn?)` Waits for the pending DOM updates to flush. See [`$nextTick`](/guide/properties#nexttick) for the template-facing form. ## What Lune does not include `@lune-js/core` deliberately leaves out parts of `@vue/reactivity`: there is no `ref()` family, no `computed()`, no `watch()`, and no `effectScope()`, and collections such as `Map` and `Set` are not reactive sources. Use JavaScript getters for derived values, and `effect()` where you would reach for `watch()`. If you need the full API, install [`@vue/reactivity`](https://www.npmjs.com/package/@vue/reactivity) alongside Lune. ## Best Practices - **Use `reactive` for state objects**: This is the most common pattern for defining your application state. - **Use getters for derived values**: Use JavaScript getters in your reactive objects for computed-like behavior: ```js const state = reactive({ count: 0, get double() { return this.count * 2; } }); ``` - **Use `effect` for side effects**: Use it when you need to react to state changes with side effects like logging, network requests, or DOM manipulation.