Eric Jorgensen
Eric Jorgensen

Reputation: 2052

mobx observer suddenly not rerendering when observable changes

My app stopped updating on observable changes and I'm going crazy trying to figure out why. The code below shows only "Counter: 5" on the screen even though the console shows that it is updating. The relevant parts of package.json are:

{
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
  },
  "dependencies": {
    "mobx": "^6.0.4",
    "mobx-react": "^7.0.5",
    "react": "17.0.0",
    "react-dom": "17.0.0",
    "react-icons": "^4.1.0",
    "react-router-dom": "^5.2.0",
    "typescript": "^4.0.3",
  },
  "devDependencies": {
    "babel-preset-mobx": "^2.0.0",
    "react-app-rewire-yaml": "^1.1.0",
    "react-scripts": "^4.0.1"
  }
}

import React from "react";
import ReactDOM from "react-dom";
import "./index.css"
import { inject, observer, Provider } from "mobx-react";
import { observable } from "mobx";

class TestModel
{
    @observable counter = 5;
    start() {
        setInterval(() => {this.counter++; console.log(this.counter)}, 1000);
    }
}

@inject("testModel")
@observer 
class TestPage extends React.Component<{testModel?: TestModel}> 
{
    render() {
        return <div><h1>Counter: {this.props.testModel.counter}</h1></div>
    }
}

const theTestModel = new TestModel();
theTestModel.start();

ReactDOM.render(
    <Provider testModel={theTestModel}> 
        <TestPage />
    </Provider>,
    document.getElementById("root")
);

EDIT:

Turns out I needed to call makeObservable(this) in the constructor of my TestModel, plus I had to pull out the side effect into an action context like this:

@action incrementCounter = () => {
    this.counter++; 
    console.log(this.counter)
}

start() {
    setInterval(this.incrementCounter, 1000);
}

Upvotes: 4

Views: 1400

Answers (1)

Tholle
Tholle

Reputation: 112777

Since [email protected] decorators are not enough. You have to make your class observable manually with makeObservable as well.

import { observable, makeObservable } from "mobx";

class TestModel {
    @observable counter = 5;

    constructor() {
        makeObservable(this);
    }

    start() {
        setInterval(() => {this.counter++; console.log(this.counter)}, 1000);
    }
}

Upvotes: 4

Related Questions