Skip to main content

What does reaction() do?

What is reaction()

reaction() is a MobX function that reacts (reactively) to a change in specific observable data and runs a side effect when it changes.

You could call it an analog of React's useEffect(), but it works at the MobX level, without any React component involved.


1. Basic syntax

javascript
import { observable, reaction } from "mobx" const price = observable.box(100) const quantity = observable.box(2) // reaction: watch for a change in total reaction( () => price.get() * quantity.get(), // tracker function (what to watch) (total, prevTotal) => { // effect (what to do on change) console.log(`Total changed: ${prevTotal}${total}`) } ) price.set(120) // Total changed: 200 → 240 quantity.set(3) // Total changed: 240 → 360

MobX:

  1. Calls the "tracker" (the first function) to figure out the dependencies,
  2. Watches them,
  3. Every time the result changes, it calls the side effect (the second function).

2. How it differs from autorun()

autorun() runs every time any dependent observable used inside its body changes. reaction() is more targeted: it tracks only what the first function (the selector) returns.

autorun()reaction()
What it tracksEverything used inside the bodyOnly the tracker function's result
When it's calledEvery time a dependency changesOnly if the result actually changed
Used forLogging, general reactionsPrecise control over side effects

In other words, reaction() is "fine-tuned" reactive side effects.


3. Example filtering out changes

javascript
import { makeAutoObservable, reaction } from "mobx" class CartStore { items = [] constructor() { makeAutoObservable(this) // watch the number of items reaction( () => this.items.length, (count) => { console.log(`Item count changed: ${count}`) } ) } add(item) { this.items.push(item) } } const cart = new CartStore() cart.add("T-shirt") // → Item count changed: 1 cart.add("Jeans") // → Item count changed: 2

Here the reaction fires only when the array's length changes, not on every change to items.


4. reaction() parameters

javascript
reaction( expression, // a function that returns "what to track" effect, // a function called on change options? // options )

Options:

OptionWhat it doesExample
fireImmediatelyrun the effect immediately on initialization{ fireImmediately: true }
equalsa custom comparison function (default !==){ equals: (a, b) => JSON.stringify(a) === JSON.stringify(b) }
delaydelay before calling the effect (debounce){ delay: 300 }
namea name for debugging{ name: "cartReaction" }

Example with fireImmediately

javascript
reaction( () => store.user, (user) => { console.log("Current user:", user) }, { fireImmediately: true } )

Logs the user right on initialization, then on every change to store.user.


5. A "side effect" example (an API request)

javascript
reaction( () => store.searchQuery, async (query) => { if (query.length < 3) return const results = await api.search(query) store.results = results }, { delay: 400 } // debounce )

This is a classic scenario: reacting to an observable change (e.g. a search string), and running an asynchronous effect (an API request).


6. Difference from computed

computedreaction
What it doesComputes a valueTriggers a side effect
Returns somethingYesNo
Caches the resultYesNo
Changes stateNoCan
Used forDerived dataSide effects

computed is a "pure" value, reaction is a "dirty action" (an effect).


7. Example in a class

javascript
class AuthStore { user = null constructor() { makeAutoObservable(this) reaction( () => this.user?.isLoggedIn, (isLoggedIn) => { if (isLoggedIn) { console.log("User logged in") } else { console.log("User logged out") } }, { fireImmediately: true } ) } }

This lets you react to a state change (e.g. on login / logout) without logic inside UI components.


8. Cleanup (dispose)

reaction() returns a function that stops the observation:

javascript
const dispose = reaction( () => store.count, (count) => console.log("count:", count) ) dispose() // the reaction will no longer fire

This is useful for manual lifecycle management (e.g. outside React).


9. Visually

javascript
[observable][reaction → side effect]

Example: store.queryreactionapi.search(query)


Summary

reaction() is a reactive observer that watches specific data (an observable) and runs a side effect when it changes.


A way to remember it:

reaction(trackFn, effectFn) = "Watch the result of trackFn and call effectFn if it changed."


When to use it:

When you need to trigger an effect on an observable change, but not call it on every re-render. For example:

  • API requests when state changes;
  • Saving data to localStorage;
  • Logging, tracking, analytics;
  • Reacting to changes in authorization, filters, routes.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.