Skip to content

Commit

Permalink
Introduced mobx.configure({ warnOnUnsafeComputationReads: true }), …
Browse files Browse the repository at this point in the history
…implements #961
  • Loading branch information
mweststrate committed Feb 27, 2018
1 parent 856aa26 commit db3ff5b
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
* `values`, `keys`, `set`, `remove` to use objects as observable collections
* Introduced `onBecomeObserved` and `onBecomeUnobserved`
* MobX now supports development only checks and exceptions, resulting in smaller and faster production builds. The setup requirements are identical to react
* Introduced `mobx.configure({ warnOnUnsafeComputationReads: true })`

## Breaking changes

* `useStrict(boolean)` was dropped, use `configure({enforceActions: boolean})` instead
* `expr` is moved to mobx-utils. Remember, `expr(fn)` is just sugar for `computed(fn).get()`
* `createTransformer` is moved to mobx-utils
* Passing `context` explicitly to `autorun`, `reaction` etc is no longer supported. Use arrow functions or function.bind instead.
Expand Down
8 changes: 7 additions & 1 deletion src/api/configure.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { globalState } from "../core/globalstate"

export function configure(options: { enforceActions?: boolean }): void {
export function configure(options: {
enforceActions?: boolean
warnOnUnsafeComputationReads?: boolean
}): void {
if (options.enforceActions !== undefined) {
globalState.enforceActions = !!options.enforceActions
globalState.allowStateChanges = !options.enforceActions
}
if (options.warnOnUnsafeComputationReads) {
globalState.warnOnUnsafeComputationReads = !!options.warnOnUnsafeComputationReads
}
}
6 changes: 6 additions & 0 deletions src/core/computedvalue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
.name}' is being read outside a reactive context and doing a full recompute`
)
}
if (globalState.warnOnUnsafeComputationReads) {
console.warn(
`[mobx] Computed value ${this
.name} is read outside a reactive context and not actively observed. Doing a full recompute`
)
}
this.value = this.computeValue(false)
}
endBatch()
Expand Down
13 changes: 12 additions & 1 deletion src/core/globalstate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import { IObservable } from "./observable"
/**
* These values will persist if global state is reset
*/
const persistentKeys = ["mobxGuid", "spyListeners", "enforceActions", "runId"]
const persistentKeys = [
"mobxGuid",
"spyListeners",
"enforceActions",
"warnOnUnsafeComputationReads",
"runId"
]

export class MobXGlobals {
/**
Expand Down Expand Up @@ -79,6 +85,11 @@ export class MobXGlobals {
* Globally attached error handlers that react specifically to errors in reactions
*/
globalReactionErrorHandlers: ((error: any, derivation: IDerivation) => void)[] = []

/**
* Warn if computed values are accessed outside a reactive context
*/
warnOnUnsafeComputationReads = false
}

export let globalState: MobXGlobals = new MobXGlobals()
Expand Down
18 changes: 18 additions & 0 deletions test/base/strict-mode.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var mobx = require("../../src/mobx.ts")
var utils = require("../utils/test-utils")

var strictError = /Since strict-mode is enabled, changing observed observable values outside actions is not allowed. Please wrap the code in an `action` if this change is intended. Tried to modify: /

Expand Down Expand Up @@ -184,3 +185,20 @@ test("strict mode checks", function() {
mobx._resetGlobalState()
d()
})

test("warn on unsafe reads", function() {
try {
mobx.configure({ warnOnUnsafeComputationReads: true })
const x = mobx.observable({
y: 3,
get yy() {
return this.y * 2
}
})
utils.consoleWarn(() => {
x.yy
}, /is read outside a reactive context and not actively observed/)
} finally {
mobx.configure({ warnOnUnsafeComputationReads: false })
}
})
18 changes: 18 additions & 0 deletions test/utils/test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ exports.consoleError = function(block, regex) {
expect(messages).toMatch(regex)
}

exports.consoleWarn = function(block, regex) {
let messages = ""
const orig = console.warn
console.warn = function() {
Object.keys(arguments).forEach(key => {
messages += ", " + arguments[key]
})
messages += "\n"
}
try {
block()
} finally {
console.warn = orig
}
expect(messages.length).toBeGreaterThan(0)
expect(messages).toMatch(regex)
}

exports.supressConsole = function(block) {
const { warn, error } = console
Object.assign(console, {
Expand Down

0 comments on commit db3ff5b

Please sign in to comment.