Skip to content

Commit

Permalink
Merge pull request #10 from meteor-space/feature/stopping-subscriptio…
Browse files Browse the repository at this point in the history
…n-and-livequery-support

Live query support
  • Loading branch information
rhyslbw authored Aug 18, 2016
2 parents 286f7e2 + 87a7f7f commit 217b5aa
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 90 deletions.
76 changes: 20 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,71 +10,35 @@ MobX and [Tracker](https://docs.meteor.com/api/tracker.html#Tracker-autorun) can
### Usage

```javascript
// my-store.js
import { observable } from 'mobx';

export default observable({
selectedProjectId: null,
projectTodos: []
});

// autorun/todos.js
import state from '../my-store';
import * as Collections from '../../infrastructure/collections';
import { Meteor } from 'meteor/meteor';
import { observable, useStrict } from 'mobx';
import autorun, { observe } from 'meteor/space:tracker-mobx-autorun';

export default () => {
const projectId = state.selectedProjectId;
Meteor.subscribe('todos', {projectId});
// MobX ObservableArray.replace() needs to be used instad of direct assignment
// to keep observable array instance and prevent re-rendering of the whole array
state.projectTodos.replace(Collections.Todos.find({projectId}).fetch());
};

// index.js
import autorun from 'meteor/space:tracker-mobx-autorun';
import todos from './autorun/todos';
// Optionally MobX strict mode makes state in the store immutable, in that case
// state can ony be changed by MobX actions
useStrict(true);

export const todosAutorun = autorun(todos);
const Todos = new Mongo.Collection('todos');

Meteor.startup(function() {
if (Meteor.isClient) {
todosAutorun.start();
}
const state = observable({
selectedProjectId: null,
 projectTodos: []
});

```

### Usage with MobX _strict mode_
Using MobX [actions](https://mobxjs.github.io/mobx/refguide/action.html)
is mandatory when strict mode is enabled.

```javascript
// index.js - enabling MobX strict mode
import { useStrict } from 'mobx';
useStrict(true);

// actions/projects.js
import state from '../store';
import { action } from 'mobx';
const syncProjectTodos = autorun(() => {
 const projectId = state.selectedProjectId;
 const handle = Meteor.subscribe('todos', { projectId });
const cursor = Todos.find({ projectId });
observe('todosAutorun', state.projectTodos, handle, cursor);
});

export const selectProject = action('selectProject', (projectId) => {
state.selectedProjectId = projectId;
// Starting autorun on startup or when needed
Meteor.startup(() => {
 if (Meteor.isClient) syncProjectTodos().start();
});

// autorun/todos.js
import state from '../my-store';
import * as Collections from '../../infrastructure/collections';
import { Meteor } from 'meteor/meteor';
import { action } from 'mobx';

export default () => {
const projectId = state.selectedProjectId;
Meteor.subscribe('todos', {projectId});
action('updateTodosFromAutorun', (todos) => {
state.projectTodos.replace(todos);
})(projectId ? Collections.Todos.find({projectId}).fetch() : []);
};
// Stopping autorun
syncProjectTodos().stop();

```

Expand Down
34 changes: 34 additions & 0 deletions autorun.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Tracker } from 'meteor/tracker';
import { autorun } from 'mobx';

export default (trackerMobxAutorun) => {
let mobxDisposer = null;
let computation = null;
let hasBeenStarted;
return {
start() {
let isFirstRun = true;
computation = Tracker.autorun(() => {
if (mobxDisposer) {
mobxDisposer();
isFirstRun = true;
}
mobxDisposer = autorun(() => {
if (isFirstRun) {
trackerMobxAutorun();
} else {
computation.invalidate();
}
isFirstRun = false;
});
});
hasBeenStarted = true;
},
stop() {
if (hasBeenStarted) {
computation.stop();
mobxDisposer();
}
}
};
};
38 changes: 4 additions & 34 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,10 @@
import { Tracker } from 'meteor/tracker';
import { checkNpmVersions } from 'meteor/tmeasday:check-npm-versions';
import observeCursor from './observe-cursor';
import autorun from './autorun';

checkNpmVersions({
'mobx': '2.x'
}, 'space:tracker-mobx-autorun');

const { autorun } = require('mobx');

export default (trackerMobxAutorun) => {
let mobxDisposer = null;
let computation = null;
let hasBeenStarted;
return {
start() {
let isFirstRun = true;
computation = Tracker.autorun(() => {
if (mobxDisposer) {
mobxDisposer();
isFirstRun = true;
}
mobxDisposer = autorun(() => {
if (isFirstRun) {
trackerMobxAutorun();
} else {
computation.invalidate();
}
isFirstRun = false;
});
});
hasBeenStarted = true;
},
stop() {
if (hasBeenStarted) {
computation.stop();
mobxDisposer();
}
}
};
};
export default autorun;
export const observe = observeCursor;
37 changes: 37 additions & 0 deletions observe-cursor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Tracker } from 'meteor/tracker';
import { action } from 'mobx';

export default (actionPrefix = '', observableArray, handle, cursor) => {

if (handle.ready()) {
// initially fetch all documents and store them in the observable array
Tracker.nonreactive(() => {
action(`${actionPrefix}: initial fetch`, (comments) => {
observableArray.replace(comments);
})(cursor.fetch());
});

// observe changes after initial fetch
cursor.observe({
// _suppress_initial suppresses addedAt callback for documents initially fetched
_suppress_initial: true,
addedAt: action(`${actionPrefix}: document added`, (document, atIndex) => {
observableArray.splice(atIndex, 0, document);
}),
changedAt: action(`${actionPrefix}: document changed`, (newDocument, oldDocument, atIndex) => {
observableArray.splice(atIndex, 1, newDocument);
}),
removedAt: action(`${actionPrefix}: document removed`, (oldDocument, atIndex) => {
observableArray.splice(atIndex, 1);
}),
movedTo: action(`${actionPrefix}: document moved`, (document, fromIndex, toIndex) => {
observableArray.splice(fromIndex, 1);
observableArray.splice(toIndex, 0, document);
}),
});
} else {
action(`${actionPrefix}: initialized`, () => {
observableArray.clear();
})();
}
};

0 comments on commit 217b5aa

Please sign in to comment.