diff --git a/CHANGELOG.md b/CHANGELOG.md index cd37e12af..dda116046 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 2.7.0 +# 3.0.0 ### Automatic inference of computed properties has been deprecated. @@ -84,6 +84,11 @@ See [#621](https://github.com/mobxjs/mobx/issues/621) * `ObservableMap.toJs` (use `toJS`) * invoking `observe` and `inject` with plain javascript objects +# 2.6.3 + +* Fixed #603: exceptions in transaction breaks future reactions +* Improved typings of `toJS` +* Introduced `setReactionScheduler`. Internal api used by mobx-react@4 to be notified when reactions will be run # 2.6.2 diff --git a/README.md b/README.md index eaa2b9fa3..6b25f8e63 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ _Simple, scalable state management_ [![Coverage Status](https://coveralls.io/repos/mobxjs/mobx/badge.svg?branch=master&service=github)](https://coveralls.io/github/mobxjs/mobx?branch=master) [![Join the chat at https://gitter.im/mobxjs/mobx](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mobxjs/mobx?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Discuss MobX on Hashnode](https://hashnode.github.io/badges/mobx.svg)](https://hashnode.com/n/mobx) +[![OpenCollective](https://opencollective.com/mobx/backers/badge.svg)](#backers) +[![OpenCollective](https://opencollective.com/mobx/sponsors/badge.svg)](#sponsors) [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://mobxjs.github.io/mobx/donate.html) ![npm install mobx](https://nodei.co/npm/mobx.png?downloadRank=true&downloads=true) @@ -114,7 +116,7 @@ If you are using React, you can turn your (stateless function) components into r ```javascript import React, {Component} from 'react'; import ReactDOM from 'react-dom'; -import {observer} from "mobx-react"; +import {observer} from 'mobx-react'; @observer class TodoListView extends Component { @@ -293,3 +295,72 @@ See the [changelog](https://github.com/mobxjs/mobx/blob/master/CHANGELOG.md#200) Was MobX key in making your project a success? Share the victory by using the [donate button](https://mobxjs.github.io/mobx/donate.html)! MobX is developed largely in free time, so any ROI is appreciated :-). If you leave a name you will be added to the [sponsors](https://github.com/mobxjs/mobx/blob/master/sponsors.md) list :). + +### Backers +Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/mobx#backer)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### Sponsors + +Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/mobx#sponsor)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/core/reaction.ts b/src/core/reaction.ts index 94376fa4b..0985d72ea 100644 --- a/src/core/reaction.ts +++ b/src/core/reaction.ts @@ -159,10 +159,16 @@ WhyRun? reaction '${this.name}': */ const MAX_REACTION_ITERATIONS = 100; +let reactionScheduler: (fn: () => void) => void = f => f(); + export function runReactions() { // invariant(globalState.inBatch > 0, "INTERNAL ERROR runReactions should be called only inside batch"); if (globalState.isRunningReactions === true || globalState.inTransaction > 0) return; + reactionScheduler(runReactionsHelper); +} + +function runReactionsHelper() { globalState.isRunningReactions = true; const allReactions = globalState.pendingReactions; let iterations = 0; @@ -184,3 +190,8 @@ export function runReactions() { } export const isReaction = createInstanceofPredicate("Reaction", Reaction); + +export function setReactionScheduler(fn: (f: () => void) => void) { + const baseScheduler = reactionScheduler; + reactionScheduler = f => fn(() => baseScheduler(f)); +} diff --git a/src/mobx.ts b/src/mobx.ts index b0be7c908..52db02f17 100644 --- a/src/mobx.ts +++ b/src/mobx.ts @@ -65,6 +65,7 @@ import { allowStateChanges } from "./core/action"; import { spyReport, spyReportEnd, spyReportStart, isSpyEnabled } from "./core/spy"; import { Lambda } from "./utils/utils"; import { isComputingDerivation } from "./core/derivation"; +import { setReactionScheduler } from "./core/reaction"; export const extras = { allowStateChanges, @@ -79,7 +80,8 @@ export const extras = { shareGlobalState, spyReport, spyReportEnd, - spyReportStart + spyReportStart, + setReactionScheduler }; // Experimental or internal api's (exposed for testing for example) diff --git a/test/api.js b/test/api.js index 73e475f81..3ea722150 100644 --- a/test/api.js +++ b/test/api.js @@ -66,6 +66,7 @@ test('correct api should be exposed', function(t) { 'isComputingDerivation', 'isSpyEnabled', 'resetGlobalState', + 'setReactionScheduler', 'shareGlobalState', 'spyReport', 'spyReportEnd', diff --git a/test/observables.js b/test/observables.js index ea24bbb62..37b7bbdf2 100644 --- a/test/observables.js +++ b/test/observables.js @@ -1621,6 +1621,14 @@ test('603 - transaction should not kill reactions', t => { } + t.equal(a.observers.length, 1) + t.equal(d.$mobx.observing.length, 1) + t.deepEqual(__mobxGlobal.inBatch, 0) + t.deepEqual(__mobxGlobal.inTransaction, 0) + t.deepEqual(__mobxGlobal.pendingReactions.length, 0) + t.deepEqual(__mobxGlobal.pendingUnobservations.length, 0) + t.deepEqual(__mobxGlobal.trackingDerivation, null) + t.equal(b, 2) a.set(3) t.equal(b, 3) diff --git a/test/perf/perf.txt b/test/perf/perf.txt new file mode 100644 index 000000000..2c3d56395 --- /dev/null +++ b/test/perf/perf.txt @@ -0,0 +1,51 @@ + +One observers many observes one - Started/Updated in 35/26 ms. +500 props observing sibling - Started/Updated in 3/5 ms. +Late dependency change - Updated in 59ms. +Unused computables - Updated in 0 ms. +Unused observables - Updated in 9 ms. +Array reduce - Started/Updated in 30/25 ms. +Array loop - Started/Updated in 125/173 ms. +Order system batched: false tracked: true Started/Updated in 448/44 ms. +Order system batched: true tracked: true Started/Updated in 93/43 ms. +Order system batched: false tracked: false Started/Updated in 131/65 ms. +Order system batched: true tracked: false Started/Updated in 110/46 ms. + +Create array - Created in 473ms. + +Create array (non-recursive) Created in 169ms. +Observable with many observers + dispose: 1240ms +expensive sort: created 5023 +expensive sort: updated 15817 +expensive sort: disposed641 +native plain sort: updated 1643 +computed memoization 1ms +create folders 1ms. +create displayfolders 1ms. +create text 271ms. +collapse folder 1ms. +uncollapse folder 0ms. +change name of folder 327ms. +search 47ms. +unsearch 228ms. +reactive folder tree [total] + 878ms. +create folders 28ms. +create displayfolders 1ms. +create text 116ms. +collapse folder 3ms. +uncollapse folder 6ms. +change name of folder 10ms. +search 29ms. +unsearch 20ms. +reactive folder tree [total] + 214ms. +create boxes 106ms. +mutations 380ms. +total 498ms. +create boxes 118ms. +mutations 945ms. +total 1175ms. + + +Completed performance suite in 30.532 sec. \ No newline at end of file