Mobx: context null in store methods

Created on 17 May 2016  Â·  7Comments  Â·  Source: mobxjs/mobx

Hi, I am trying to write to write the change state methods inside the store.
Example

import { observable } from 'mobx'
import faker from 'faker'

export default observable({
  requester: {
    name: ''
  },
  changeName: function (e) {
    this.name = e.target.value
  }
})

I thought that it was a good idea, because in this way I can just use directly the function in React render method.
Why it works only if I don't bind the function directly?

<input onChange={userStore.changeName} /> // Does not work. This is null inside function
<input onChange={(e) => { userStore.changeName(e) }} /> // Works

Most helpful comment

This is more a generic JS issue, but personally I think

<input onChange={(e) => { userStore.changeName(e.target.value) }} /> is the proper way to do this, as it gives the flexibility of also doing stuff with e like preventing default, logic which doesn't belong in a store.

otherwise <input onChange={userStore.changeName.bind(userStore)} /> would also work.

In any case I would restructure your store a bit, so that your store _methods_ are not passed through observable and accidentally converted in computed properties:

const store = observable({
  requester: {
    name: ''
  }
});

store.changeName = function (newName) {
  this.name = newName
}// optionally you can bind here already so that it is not needed in the component :-) : .bind(store)

export default store;

All 7 comments

@giacomorebonato

If I were to guess, it might be because this is set to the wrong value in your first line. Could you try

<input onChange={userStore.changeName.bind(this)} />

for me to confirm? If that's not it, then I'm not sure what the problem could be.

In this case the context is undefined.

P.S. I am inside of a stateless functional component

It is not really a problem, but I was thinking about a pattern to suggest... if it would have worked.

if it would have worked.

Ah so it didn't work 😓 ... hopefully someone else can help then. I've been on a pretty bad streak of helping people haha.

This is more a generic JS issue, but personally I think

<input onChange={(e) => { userStore.changeName(e.target.value) }} /> is the proper way to do this, as it gives the flexibility of also doing stuff with e like preventing default, logic which doesn't belong in a store.

otherwise <input onChange={userStore.changeName.bind(userStore)} /> would also work.

In any case I would restructure your store a bit, so that your store _methods_ are not passed through observable and accidentally converted in computed properties:

const store = observable({
  requester: {
    name: ''
  }
});

store.changeName = function (newName) {
  this.name = newName
}// optionally you can bind here already so that it is not needed in the component :-) : .bind(store)

export default store;

Wow, thank you for the explanation it was what I needed.

Can I propose some examples to add to the documentation?

sure! that is always appreciated. there should be edit buttons in the docs

Op di 17 mei 2016 14:23 schreef Giacomo Rebonato [email protected]:

Can I propose some examples to add to the documentation?

—
You are receiving this because you commented.

Reply to this email directly or view it on GitHub
https://github.com/mobxjs/mobx/issues/251#issuecomment-219701652

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mweststrate picture mweststrate  Â·  61Comments

mweststrate picture mweststrate  Â·  105Comments

flipjs picture flipjs  Â·  31Comments

AriaFallah picture AriaFallah  Â·  63Comments

mweststrate picture mweststrate  Â·  75Comments