9

Upon page load, I see "hi2" When I click the button, nothing happens. I tried with setUser as well.

I suspect I'm just editing the props themselves and somehow the observable is not being triggered?

See sample code of it not working here in a brand new rails/react environment: https://github.com/bufordtaylor/mobxtest

  1. clone
  2. bundle
  3. rails s
  4. (in another process) ./bin/webpack-dev-server --host 127.0.0.1
  5. navigate to localhost:3000

======================

UPDATE:

I've reduced it to it's basic form, eliminating possible import errors, Provider errors, or constructor errors.

Here it is

import React from 'react'
import ReactDOM from 'react-dom'
import { observable, action, computed } from 'mobx';
import { Provider, inject, observer } from 'mobx-react';


class UserStore {

  @action setUser(val) {
    console.log(val);
    this.user = val;
  }

  @observable user = "default";
}

const userStore = new UserStore();

@observer
class Hello extends React.Component {
  render() {
    return (
      <div>
        hi2 {this.props.userStore.user}
        <button onClick={this.props.userStore.setUser.bind(this,"fwefwe")}>faew</button>
      </div>
    )
  }
}

document.addEventListener('DOMContentLoaded', () => {
  ReactDOM.render(
    <Hello userStore={userStore} />,
    document.getElementById('app'),
  )
})
Ayushya
  • 5,820
  • 3
  • 30
  • 51
wiznaibus
  • 621
  • 3
  • 8
  • 16
  • [**It works for me**](http://jsbin.com/xosusiduci/edit?js,output). Can you work out what differs in you case? – Tholle Oct 01 '17 at 14:04
  • No luck. I copied your code directly into my editor. @Tholle. – wiznaibus Oct 01 '17 at 14:13
  • That's annoying. The only thing I see that looks a little bit suspicious is the `import UserStore from '../bundles/User/stores/UserStore';`. Is `../bundles/User/stores/UserStore` the intended import? – Tholle Oct 01 '17 at 14:21
  • I thought that after I saw your code. But after I literally copy/pasted your code into one big file, it still runs as previously described. I'm currently loading up a brand new app to check there. – wiznaibus Oct 01 '17 at 14:22
  • Added new rails/react app in the question. Your code is copied directly into `app/javascript/packs/hello_react.jsx` file, @tholle. Same problem unfortunately. – wiznaibus Oct 01 '17 at 14:37
  • 1
    Bummer. Could you try to put `transform-decorators-legacy` first in the list of babel plugins? – Tholle Oct 01 '17 at 15:24
  • 2
    I went mad over this problem. I was hunched over my laptop since 4PM yesterday, barely slept, drank way too much coffee, snapped at my wife, and finally...I have a resolution. Thank you @Tholle! – wiznaibus Oct 01 '17 at 15:28

6 Answers6

8

My problem was the order of wrapping the component, because I was using Material UI framework.

Wrong:

export inject('store')(observer(withStyles(styles)(MyComponent)));

Correct:

export withStyles(styles)(inject('store')(observer(MyComponent)));

So, it's important the order with MobX and React Material UI.

Alin Ciocan
  • 2,713
  • 3
  • 29
  • 43
  • You save my life – user3896501 Oct 31 '19 at 11:56
  • @ArjunTRaj maybe it's something else that is messing with Mobx. Try to only use inject and observer on the component and see if that's the issue. Otherwise, it might be something different. I have discovered that unless you read from the store in the component, the render it's not triggered. – Alin Ciocan Nov 26 '19 at 11:22
5

Your code looks sound. I think you have stumbled upon an issue discussed in the How to (not) use decorators part of the documentation. It is important that transform-decorators-legacy is first in the list of babel plugins.

Tholle
  • 83,208
  • 13
  • 152
  • 148
  • 1
    I ran into this issue recently while using parcel-bundler. This is due to what appears to be a bug in parcel not properly parsing tsconfig.json files. See [here](https://github.com/parcel-bundler/parcel/issues/2129#issuecomment-459572127). – Adam Mazzarella Feb 01 '19 at 04:19
4

if you use the latest version of mobx, and babel version 7.12 add this to you constructor

makeObservable(this)
tarik203
  • 315
  • 2
  • 9
2
<button onClick={this.props.userStore.setUser.bind(this,"fwefwe")}>faew</button>

Be careful. You are binding this. This in this case is the instance of the Hello Component. Now the this in the setUser function points to the Hello Component. So setUser will set a property user in the Hello Component.

 @action setUser(val) {
    console.log(val);
    this.user = val; // This this now points to the Hello Component.
  }

To understand what I mean, you can set a breakpoint on the setUser method, then inspect the variable this. You will see that it points to the Hello Component and not to your stores instance.

Instead do the following:

<button onClick={() => { this.props.userStore.setUser("fwefwe"); }}>faew</button>

Here I am creating a lambda that calls setUser on the user store. Because I am using a lambda here, the this in this.props.userStore points to the Hello Component.

Daniel
  • 1,755
  • 11
  • 17
2

For anyone arriving here, make sure you're not being a complete idiot like me and that you didn't forget to add the @observer decorator before the class component.

(Or the @observable decorator in the store)

God, wasted a full day on that

jonyB
  • 1,084
  • 1
  • 5
  • 8
  • 2
    You are not alone man, I also forgot to wrap my functional component with observer function. 10K+ reputation... mean nothing :) – shift66 Feb 18 '21 at 07:17
0

I had similar issue, I was using arrow function for render method:

render = (): React.ReactNode

correct should be:

render(): React.ReactNode

still not sure why first case confuses mobx.

Ivan
  • 130
  • 8