Search code examples
javascriptreactjsmobxmobx-react

Mobx-react no render but state changed


I decided to try Mobx and faced the problem of the component's lack of response to a changing field in the repository. I looked at similar topics, but I still don't understand what the problem is. If you print the property value to the console after the change, you see the actual result.

index.js

import React from 'react';
import ReactDOM from 'react-dom';

import { Provider } from "mobx-react";
import AppStore from "./AppStore";

import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <Provider AppStore={AppStore}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

App.js

import React, { Component } from "react";
import { inject, observer } from "mobx-react";

@inject('AppStore')
@observer class App extends Component {
  render() {
    const { AppStore } = this.props;
    console.log(AppStore);
    return(
      <div className="App">
        { this.props.AppStore.counter }
        <hr/>
        <button onClick={this.props.AppStore.increment}>+</button>
        <button onClick={this.props.AppStore.decrement}>-</button>
      </div>
    )
  }
}

export default App;

AppStore.js

import { observable, action } from "mobx";

class AppStore {
  @observable counter = 0;
  @action increment = () => {
    this.counter = this.counter + 1;
    console.log(this.counter);
  }
  @action decrement = () => {
    this.counter = this.counter - 1;
    console.log(this.counter);
  }
}

const store = new AppStore();
export default store;

Solution

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

    class AppStore {
      @observable counter = 0;
    
      constructor() {
        makeObservable(this);
      }
    
      @action increment = () => {
        this.counter = this.counter + 1;
      }
      @action decrement = () => {
        this.counter = this.counter - 1;
      }
    }