Chris
Chris

Reputation: 1587

React Mobx - component not updating after store change

Using Mobx, after updating the store (i.e. clicking the button) the component does not re-render. I've installed mobx devtools which shows nothing after the initial load, and there is no error in the console. Any ideas what I've done wrong?

Store.js:

import { observable } from 'mobx';

class Store {

    @observable me;

    constructor() {
        this.me = 'hello';
    }

    change_me(){
        this.me = 'test 1234';

    }

}


export default Store;

layout.js:

import React from "react";
import { observer } from 'mobx-react';


@observer
export default class Layout extends React.Component{

    render(){

        return(
            <div>
                <h1>{this.props.store.me}</h1>
              <button onClick={this.on_change}>Change</button>
            </div>
        )
    }

    on_change = () => {
        this.props.store.change_me();
    }
}

index.js:

import React from "react";
import ReactDOM from "react-dom";
import Layout from "./components/Layout";
import Store from "./Store";
import DevTools, { configureDevtool } from 'mobx-react-devtools';

// Any configurations are optional
configureDevtool({
    // Turn on logging changes button programmatically:
    logEnabled: true,
    // Turn off displaying conponents' updates button programmatically:
    updatesEnabled: false,
    // Log only changes of type `reaction`
    // (only affects top-level messages in console, not inside groups)
    logFilter: change => change.type === 'reaction',
});


const app = document.getElementById('app');
const store = new Store();

ReactDOM.render(

    <div>
        <Layout store={store} />
        <DevTools />
    </div>
, app);

Upvotes: 12

Views: 18622

Answers (4)

Just add makeObservable(this); in constructor function like below

    constructor() {
       makeObservable(this);
    }

Upvotes: 2

dpastoor
dpastoor

Reputation: 146

Watch the binding of the this context.

<button onClick={this.on_change}>Change</button>

the this reference will not be to the class, so likely when you are actually clicking it is going to say something along the lines of no props on undefined. Changing to:

  <button onClick={this.on_change.bind(this)}>Change</button>

should fix it. Or better yet, bind the context in the constructor so its not re-binding on every render

 constructor(props) {
   super(props)
   this.on_change = this.on_change.bind(this)
 }

then you can go back to your

Upvotes: -1

Nopik
Nopik

Reputation: 542

My guess would be to have uninitialized @observable. It is very counter-intuitive, but Babel doesn't handle those well. Even adding @observable me = undefined might help (see the generated js code when you assign something there. Generally I'd remove constructor completely and move the initialization to declaration (i.e. @observable me = "hello" an no constructor). It should then work fine.

Upvotes: 2

cdoc
cdoc

Reputation: 21

I would start by adding @action to your change_me() function. From what I understand, it's not always completely required, but I have encountered problems like this in my own code several times when I've forgotten to add it.

Additionally post your .babelrc as @mweststrate suggested, as it will help others to check that the proper plugins are loaded.

Upvotes: 2

Related Questions