NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #4512 most downloaded on npm
Simple, scalable state management.
Last release 29 days ago
19 Aug 2026
Release timing varies
gaps range from 1 weeks to 7 months
Nearly every release is documented
notes for 59 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
11 years old
264 releases · first in 2016
Improved typings of IObservableArray.intercept: use more restrictive types for change parameter of handler, by @bvanreeven
IObservableArray.intercept: use more restrictive types for change parameter of handler, by @bvanreevenRestored default export (and added warning), which broke code that was importing mobx like import mobx from "mobx". Use import * as mobx from "mobx" o
default export (and added warning), which broke code that was importing mobx like import mobx from "mobx". Use import * as mobx from "mobx" or use named importes instead. By @andykog, see #1043, #1050One column per quarter.
Fixed issue where array.remove did not work correctly in combination with extras.interceptReads
array.remove did not work correctly in combination with extras.interceptReadsFixed 3.1.12 / 3.1.13 module packing. See #1039; module target is now transpiled to ES5 as well
module target is now transpiled to ES5 as wellNothing published for this version
Using rollup as bundler, instead of custom hacked build scripts, by @rossipedia, see #1023
Nothing published for this version
Fixed flow typings for when, by @jamsea
when, by @jamseamap.replace, by @leader22observableArray.findIndex, by @leader22autorun / autorunAsync to better support async / await, by @capajaction.bound, see #803Introduced explicit .get(index) and .set(index, value) methods on observable arrays, for issues that have trouble handling many property descriptors o
.get(index) and .set(index, value) methods on observable arrays, for issues that have trouble handling many property descriptors on objects. See also #734onBecomeObserved twice in row, fixes #874, #898IReactionDisposerFixed edge case where autorun was not triggered again if a computed value was invalidated by the reaction itself, see #916, by @andykog
autorun was not triggered again if a computed value was invalidated by the reaction itself, see #916, by @andykogcreateTransformer, See #920 by @dnakovisArrayLike, see #904, by @mohsen1Nothing published for this version
Reverted ES2015 module changes, as they broke with webpack 2 (will be re-released later)
Nothing published for this version
Improved typings of map changes, see #847, by @hediet
reaction if fireImmediately was combined with delay option, see #837, by @SaboteurSpkObservable maps initialized from ES6 didn't deeply convert their values to observables. (fixes #869,by @ggarek)
Make sure that ObservableArray.replace can handle large arrays by not using splats internally. (See e.g. #859)
ObservableArray.replace can handle large arrays by not using splats internally. (See e.g. #859)ObservableArray.spliceWithArray, that unlike a normal splice, doesn't use a variadic argument list so that it is possible to splice in new arrays that are larger then allowed by the callstack.Fixed incompatiblity issue with mobx-react@4.1.0
mobx-react@4.1.0Strict mode has been relaxed a bit in this release. Also computed values can now better handle creating new observables (in an action if needed). The
Strict mode has been relaxed a bit in this release. Also computed values can now better handle creating new observables (in an action if needed). The semantics are now as follows:
In order words: Observables that are not in use anywhere yet, are not protected by MobX strict mode. This is fine as the main goal of strict mode is to avoid kicking of reactions at undesired places. Also strict mode enforces batched mutations of observables (through action). However, for unobserved observables this is not relevant; they won't kick of reactions at all.
This fixes some uses cases where one now have to jump through hoops like:
runInAction or action. See issue #563Note that the following constructions are still anti patterns, although MobX won't throw anymore on them:
autorun or reaction instead.Note that observables that are not in use by a reaction, but that have .observe listeners attached, do not count towards being observed.
Observe and intercept callbacks are concepts that do not relate to strict mode, actions or transactions.
NaN === NaN, See #805 by @andykogFixed issue where MobX failed on environments where Map is not defined, #779 by @dirtyrolf
Map is not defined, #779 by @dirtyrolfSymbol.toPrimitive() and valueOf(), see #773 by @eladnava #GoodnessSquadRe-introduced structural comparison. Seems we couldn't part from it yet :). So the following things have been added:
struct option to reaction (alias for compareStructural, to get more consistency in naming)observable.struct, as alias for observable.deep.structobservable.deep.struct: Only stores a new value and notify observers if the new value is not structurally the same as the previous value. Beware of cycles! Converts new values automatically to observables (like observable.deep)observable.ref.struct: Only stores a new value and notify observers if the new value is not structurally the same as the previous value. Beware of cycles! Doesn't convert the new value into observables.extras.deepEquals: Check if two data structures are deeply equal. supports observable and non observable data structures.Nothing published for this version
Nothing published for this version
toString() of observable arrays now behaves like normal arrays (by @capaj, see #759)
toString() of observable arrays now behaves like normal arrays (by @capaj, see #759)toJSby @jamsea (#758)Nothing published for this version
Nothing published for this version
…of observables more uniform, and removing deprecated stuff.
The changelog of MobX 3 might look quite overwhelming, but migrating to MobX 3 should be pretty straight forward nonetheless.
The api has now become more layered, and the api is more uniform and modifiers are cleaned up.
In practice, you should check your usage of modifiers (asFlat, asMap etc.). Besides that the migration should be pretty painless.
Please report if this isn't the case!
Note that no changes to the runtime algorithm where made, almost all changes evolve in making the creation of observables more uniform, and removing deprecated stuff.
Nothing published for this version
Nothing published for this version
Nothing published for this version
A deprecation message will now be printed if creating computed properties while relying on automatical inferrence of argumentless functions as compute…
A deprecation message will now be printed if creating computed properties while relying on automatical inferrence of argumentless functions as computed values. In other words, when using observable or extendObservable in the following manner:
const x = observable({
computedProp: function () {
return someComputation
}
})
// Due to automatic inferrence now available as computed property:
x.computedProp
// And not !
x.computedProp()
Instead, to create a computed property, use:
observable({
get computedProp() {
return someComputation
}
})
or alternatively:
observable({
computedProp: computed(function () {
return someComputation
})
})
This change should avoid confusing experiences when trying to create methods that don't take arguments. The current behavior will be kept as-is in the MobX 2.* range, but from MobX 3 onward the argumentless functions will no longer be turned automatically into computed values; they will be treated the same as function with arguments. An observable reference to the function will be made and the function itself will be preserved. See for more details #532
N.B. If you want to introduce actions on an observable that modify its state, using action is still the recommended approach:
observable({
counter: 0,
increment: action(function () {
this.counter++
})
})
By the way, if you have code such as:
observable({
@computed get someProp() { ... }
});
That code will no longer work. Rather, reactions will fail silently. Remove @computed.
Note, this only applies when using observable in this way; it doesn't apply when using
@observable on a property within a class declaration.
toJS sometimes failing to convert objects decorated with @observable (cause: isObservable sometimes returned false on these object)when / autorun / reaction; they all return a disposer function.Nothing published for this version
Added move operation to observable array, see #697
move operation to observable array, see #697Fixed potential clean up issue if an exception was thrown from an intercept handler
asStructure (by @nidu, see #687)computed(asStructure(() => expr)) (by @yotambarzilay, see #685)Fixed #603: exceptions in transaction breaks future reactions
toJSsetReactionScheduler. Internal api used by mobx-react@4 to be notified when reactions will be runChanges related to toJS as mentioned in version 2.6.0 where not actually shipped. This has been fixed, so see release notes below.
toJS as mentioned in version 2.6.0 where not actually shipped. This has been fixed, so see release notes below.Introduced convenience isArrayLike: returns whether the argument is either a JS- or observable array. By @dslmeinte
isArrayLike: returns whether the argument is either a JS- or observable array. By @dslmeinte_Marked as minor release as the behavior of toJS has been changed, which might be interpreted both as bug-fix or as breaking change, depending of how…
Marked as minor release as the behavior of toJS has been changed, which might be interpreted both as bug-fix or as breaking change, depending of how you interpreted the docs
toJS: toJS will now only recurse into observable object, not all objects. The new behavior is now aligned with what is suggested in the docs, but as a result the semantics changed a bit. toJSlegacy will be around for a while implementing the old behavior. See [#589](See https://github.com/mobxjs/mobx/pull/589) for more details.instanceof operator. Should fix issues if MobX is included multiple times in the same bundle.autorun; as they won't be tracked by @jeffijoeNothing published for this version
Observable objects can now have a type: IObservableObject, see #484 by @spiffytech
Computed properties can now be created by using getter / setter functions. This is the idiomatic way to introduce computed properties from now on:
const box = observable({
length: 2,
get squared() {
return this.length * this.length
},
set squared(value) {
this.length = Math.sqrt(value)
}
})
Introduced isStrictModeEnabled(), deprecated useStrict() without arguments, see #464
computed(expr, setter) or @computed get name() { return expr } set name (value) { action }. computed can now be used as modifier in observable / extendObservable, #421, #463 (see below for example)isStrictModeEnabled(), deprecated useStrict() without arguments, see #464MobX is now able track and memoize computed values while an (trans)action is running. Before 2.5, accessing a computed value during a transaction always resulted in a recomputation each time the computed value was accessed, because one of the upstream observables (might) have changed. In 2.5, MobX actively tracks whether one of the observables has changed and won't recompute computed values unnecessary. This means that computed values are now always memoized for the duration of the current action. In specific cases, this might signficantly speed up actions that extensively make decisions based on computed values.
Example:
class Square {
@observable length = 2
@computed get squared() {
return this.length * this.length
}
// mobx now supports setters for computed values
set squared(surfaceSize) {
this.length = Math.sqrt(surfaceSize)
}
// core changes make actions more efficient if extensively using computed values:
@action stuff() {
this.length = 3
console.log(this.squared) // recomputes in both 2.5 and before
console.log(this.squared) // no longer recomputes
this.length = 4
console.log(this.squared) // recomputes in both 2.5 and before
// after the action, before 2.5 squared would compute another time (if in use by a reaction), that is no longer the case
}
}
ES5 example for setters:
function Square() {
extendObservable(this, {
length: 2,
squared: computed(
function () {
return this.squared * this.squared
},
function (surfaceSize) {
this.length = Math.sqrt(surfaceSize)
}
)
})
}
Nothing published for this version
Nothing published for this version
Fixed #503: map.delete returns boolean
runInAction, #499 by @Strateaction for better type inference, #500 by @StrateextendObservable fails on objects created with Object.create(null)asMap, by @StrateObjects with a null prototype are now considered plain objects as well
null prototype are now considered plain objects as wellNothing published for this version
Improved error message when wrongly using @computed, by @bb
@computed, by @bb (#450)observableArray.slice now automatically converts observable arrays to plain arrays, fixes #460@action decorated methods are now configurable. Fixes #441
@action decorated methods are now configurable. Fixes #441onBecomeObserved event handler is now triggered when an atom is observed, instead of when it is bound as dependency. Fixes #427 and makes atoms easier to extend.useStrict() is invoked without arguments, it now returns the current value of strict mode.autorun, autorunAsync, when and reaction. This allows reactions to be immediately disposed during the first run. See #438, by @andykog_Note: the internal version of MobX has been bumped. This version has no breaking api changes, but if you have MobX loaded multiple times in your proj
2.4.0. MobX will report this when starting.Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Fixed issue where computed values were tracked and accidentally kept alive during actions
Fixed #406: Observable maps doesn't work with empty initial value in Safari
@@iterator() or iterall in ES5 environments.Nothing published for this version
Fixed #364: Observable arrays not reacting properly to index assignments under iOS safari (mobile) 9.1.1 By @andykog
Fixed #360: Removed expensive cycle detection (cycles are still detected, but a bit later)
toJS serialization of Dates and Regexes preserves the original values@action decorated methods can now be inherited / overriddenNothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →