I have an:
Coming back to MobX after a while, using mobx 2.6.2 with mobx-react 3.5.9. This used to work in a previous version:
import * as React from "react";
import { observer } from "mobx-react";
import { observable, action } from "mobx";
@observer
export class TestComponent extends React.Component<{}, {}> {
@observable someProp: string;
@action changeSomeProp = () => { // here seems to be the issue
this.someProp = "value";
}
}
Now I get this error every time my app re-renders TestComponent with hot-reloading:
mobx.js?6a62:2508
Uncaught (in promise) TypeError: Object.defineProperty called on non-object
at Function.defineProperty (<anonymous>)
at classPropertyDecorator (eval at <anonymous> (http://localhost:3001/static/bundle.js:1613:1), <anonymous>:2508:24)
at eval (eval at <anonymous> (http://localhost:3001/static/bundle.js:1613:1), <anonymous>:31:25)
at typescriptInitializeProperty (eval at <anonymous> (http://localhost:3001/static/bundle.js:1613:1), <anonymous>:2550:5)
at Object.get (eval at <anonymous> (http://localhost:3001/static/bundle.js:1613:1), <anonymous>:2495:25)
at shouldDeleteModernInstanceMethod (eval at <anonymous> (http://localhost:3001/static/bundle.js:7927:1), <anonymous>:38:27)
at eval (eval at <anonymous> (http://localhost:3001/static/bundle.js:7927:1), <anonymous>:79:9)
at Array.forEach (native)
at deleteUnknownAutoBindMethods (eval at <anonymous> (http://localhost:3001/static/bundle.js:7927:1), <anonymous>:78:9)
at Array.forEach (native)
which corresponds to this line in the source. The problem goes away when I use a proper method instead of a class property method:
@observer
export class TestComponent extends React.Component<{}, {}> {
@observable someProp: string;
@action changeSomeProp() { // no more issues
this.someProp = "value";
}
}
I think this is a current limitation of Hot Module Reloading. I think it cannot easily be fixed until decorators have stabilized, but a simple workaround is doing changeSomeProp = action(() => { .. }) (the down side of your approach is that the action is no longer bound)
Thanks, I guess I can live without decorators in a few places.
I had the same issue when my TypeScript target language was "ES5" (default). Changing the target to "ES6" resolved the issue.
This also happens when you have an observable and action with the same name.
Took me a while to notice that silly mistake 😄
This appears to still be a problem with TypeScript and hot reloading (and I'm not able to target ES6 due to needing to support older browsers). As @mweststrate suggested, I'm finding that I have to remove all @action decorators on event handlers of the form () => {...} and replace them with action(() => {...}) to get hot reloading to work. I hope a solution becomes available at some point...
Edit
One solution that just occurred to me would be to allow an @action decorator on property sets. This is what I originally tried to do before realizing this doesn't work and trying to put them on my event handlers.
Example:
@action
set activePlan(value) {
this._activePlan = value;
}
Note that the @next version of HMR has some support for decorators afaik. (Still wouldn't trust it too much, personally I bailed out on HMR a long time ago)
Also note that computed values can have setters, and that they are actions automatically
@mweststrate,
Thanks, I did eventually come across that in the docs. Since my comment, I've developed a preference for isolating the exact line of code that modifies state and wrapping just that with runInAction (rather than wrapping the entire event handler method in action).
Example:
private onToggleBookmarked = () => {
const item = this.props.item;
runInAction(() => item.isBookmarked = !item.isBookmarked);
}
I'm having this issue in an app with React Native, out of nothing i'm getting Object.defineProperty called on non-object in the first render, but if I save any file and the app Hot reloads the problem goes away, none of the mobx code was modified, it was working OK, and bum out of nothing this error. I've tried disabling hot reloading, deleting all watchman caches, node_modules and reinstalling, etc...
The only thing that does actually stop the error is removing this line:
class AuthStore {
//........
@observable authToken = null
//..........
}
if I remove that line, code works (auth doesn't obviusly), if I replace null with an empty string '', code works, if I replace null with a random string, same error again. If I initialize it as an empty string, when I try to update it, same again "Object.defineProperty called on non-object"
The weird thing is, i didn't touch a thing in this file and suddenly this error appears
Any ideas?
Can you share your babel configuration?
Op di 22 aug. 2017 om 06:03 schreef Juan Miret notifications@github.com:
I'm having this issue in an app with React Native, out of nothing i'm
getting Object.defineProperty called on non-object in the first render, but
if I save any file and the app Hot reloads the problem goes away, none of
the mobx code was modified, it was working OK, and bum out of nothing this
error. I've tried disabling hot reloading, deleting all watchman caches,
node_modules and reinstalling, etc...The only thing that does actually stop the error is removing this line:
class AuthStore {
//........
@observable https://github.com/observable authToken = null
//..........
}if I remove that line, code works (auth doesn't obviusly), if I replace
null with an empty string '', code works, if I replace null with a random
string, same error again. If I initialize it as an empty string, when I try
to update it, same again "Object.defineProperty called on non-object"The weird thing is, i didn't touch a thing in this file and suddenly this
error appearsAny ideas?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/mobxjs/mobx/issues/655#issuecomment-323913188, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ABvGhEbo7wwX-OcPwCSeAL3cYnqyhcYzks5salL2gaJpZM4KxU9P
.
@mweststrate I'm sorry, it was a really silly mistake, one of my coworkers changed the name of an action in other store, and the new name was the same as the name of a property, and that was the root of the issue. The reason that removing the authToken line made it work is because without the token the other store would never be used. Took me a complete day to debug 😓
I have the same problem, what's the solution? I use [email protected] [email protected]
configure({enforceActions: true})
export default class Activity {
@observable adList = []
@action
async receiveAdlist (params) {
const data = await getBanner(params)
if (data.success) {
reaction(() => {
this.adList = data.data
})
}
}
@action
async addAdlist (params) {
const data = await addBanner(params)
if (data.success) {
this.receiveAdlist()
}
}
@action
async editAdlist (params) {
const data = await editBanner(params)
if (data.success) {
this.receiveAdlist()
}
}
}
@WebCaiQingChong this issue is closed. Please open a new one, including reproduction in a sandbox
For those who find themselves in this ticket, I had the problem caused by the following:
myReaction = reaction(() => this.foo, this.myAction)
@action
myAction = () => {
...
}
changing to this fixed it:
myReaction = reaction(() => this.foo, () => {
this.myAction();
})
@action
myAction = () => {
...
}
Now that I think about it, the problem might have been that I was referring to the action "before" it was defined, because of how JS's class member declarations are actually sequential.
Most helpful comment
This also happens when you have an
observableandactionwith the same name.Took me a while to notice that silly mistake 😄