Suggest an editImprove this articleRefine the answer for “What is action in MobX?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)An **`action`** in MobX is a function that changes observable data; MobX tracks all changes made inside an action and updates dependencies as a single batch. **Key point:** without an action, MobX would trigger a reaction after every mutation, but with an action all changes are grouped into one batch, so the UI re-renders only once after the action completes.Shown above the full answer for quick recall.Answer (EN)Image## Simple definition > `action` in MobX is a **function that changes observable data**. > > MobX tracks all changes made *inside an action* and updates dependencies (components, computations) **as a single batch**, without extra reactions between intermediate steps. --- ## Why action exists MobX separates two kinds of code: | Kind | Purpose | |---|---| | **Reactive** | computes or renders data (for example, a React component or `computed`) | | **Active** | *changes* data (for example, a click event, an API request, etc.) | Action is the boundary where **changes to observable state happen**. They provide: 1. **predictability** (all changes are controlled); 2. **optimization** (updates are batched); 3. **clean reactivity** (no reactions "in the middle" of computations). --- ## Example 1 - without action ```javascript import { makeObservable, observable } from 'mobx' class Counter { count = 0 constructor() { makeObservable(this, { count: observable, }) } increment() { this.count++ // MobX still works, but not optimally } } ``` Here `increment()` changes the state, but MobX does not know that this is a *controlled action*. --- ## Example 2 - with action ```javascript import { makeObservable, observable, action } from 'mobx' class Counter { count = 0 constructor() { makeObservable(this, { count: observable, increment: action, // declare it as an action }) } increment() { this.count++ } } ``` Now MobX knows that `increment()` is an **action**, and: - it does not run reactions (UI updates) *after every mutation*; - it delays the reaction until the end of the action; - it groups all changes into **a single batch** → fewer re-renders and computations. --- ## Automatic action detection If you use modern MobX (via `makeAutoObservable`), it **marks methods as `action` itself**, and getters as `computed`: ```javascript import { makeAutoObservable } from 'mobx' class TodoStore { todos = [] constructor() { makeAutoObservable(this) // everything is automatic } addTodo(text) { this.todos.push({ text, done: false }) // action } get completed() { return this.todos.filter(t => t.done) // computed } } ``` --- ## Why this matters Suppose you update several properties in a row: ```javascript userStore.updateProfile = action(() => { userStore.name = 'Alex' userStore.age = 25 userStore.email = 'alex@example.com' }) ``` Without `action`, MobX would trigger a reaction after **every assignment**, up to three re-renders in a row. With `action`, MobX does this **as one batch**, triggering the reaction only once, after the block finishes. --- ## Types of action | Type | Description | |---|---| | `action(fn)` | manually wraps a function in an action | | `@action` **(decorator)** | the old syntax for classes | | `makeObservable(..., { method: action })` | explicit declaration | | `makeAutoObservable()` | automatically detects methods as actions | --- ## Example 3 - explicit declaration outside a class ```javascript import { observable, action } from 'mobx' const state = observable({ count: 0, inc: action(function () { this.count++ }), }) ``` --- ## Under the hood Action: 1. Marks the start of a "batch of changes" (`startBatch`); 2. Disables intermediate reactions; 3. Performs the changes to the `observable`; 4. After finishing, **notifies all dependent reactions at once** (`endBatch`). This is exactly what makes MobX **highly efficient**: the UI does not re-render on every small change, only once the whole action is done. --- ## Summary | What it does | Example | |---|---| | Wraps a state change | `increment = action(() => this.count++)` | | Groups updates | One batch instead of several reactions | | Improves performance | Fewer re-renders | | Makes code predictable | All changes go through actions | | Automatically created by `makeAutoObservable` | Yes | --- ## In short > `action` is the "official place" where you change `observable` data. > It makes changes **controlled**, **batched**, and **predictable**, > providing clean reactivity and high performance.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.