javascriptmeteormeteor-tracker

Tracker.autorun only runs once


Here is what I am currently working with

class FooComponent extends Component {

  constructor(...args) {
    super(...args);

    this.state = {
      model: this.getModel()
    };
  }

  componentWillUnmount() {
    this._unmounted = true;
    this._modelComputation && this._modelComputation.stop();
    super.componentWillUnmount && super.componentWillUnmount();
  }

  getModel() {
    const model = {};

    this._modelComputation && this._modelComputation.stop();

    this._modelComputation = Tracker.autorun((computation) => {
      const { id } = this.props;
      const data = id && Collection.findOne(id);

      if (data) {
        Object.assign(model, data);
        !this._unmounted && this.forceUpdate();
      }
    });

    return model;
  }

  ...

}

Unfortunately, the reactive model does not work, and Tracker.autorun does not execute the function when the model is updated in the database. From the documentation, Collection.findOne should be reactive, right?

I am not sure what I am doing wrong. Why isn't Tracker monitoring the DB model? Why isn't the function re-evaluating Collection.findOne when the DB changes?


** Edit **

When updating the DB, I do see the collection change through meteortoys:allthings, but autorun is not re-executed.


Solution

  • Looking at how tracker-react implements it, I changed my code like so

    class FooComponent extends Component {
    
      constructor(...args) {
        super(...args);
    
        this.state = {
          model: this.getModel()
        };
      }
    
      componentWillUnmount() {
        this._unmounted = true;
        this._modelComputation && this._modelComputation.stop();
        super.componentWillUnmount && super.componentWillUnmount();
      }
    
      getModel() {
        const model = {};
    
        this._modelComputation && this._modelComputation.stop();
    
        this._modelComputation = Tracker.nonreactive(() => {
          return Tracker.autorun((computation) => {
            const { id } = this.props;
            const data = id && Collection.findOne(id);
    
            if (data) {
              Object.assign(model, data);
              !this._unmounted && this.forceUpdate();
            }
          });
        });
    
        return model;
      }
    
      ...
    
    }
    

    I don't fully understand why, but it works, now.