Mobx: Forms Problem

Created on 2 May 2016  ·  13Comments  ·  Source: mobxjs/mobx

Hello.

I'm trying to work with forms, but it is not working correctly and I think I'm missing something.

I have a todo input list and when I add two items with some text and try to edit them it doesn't work.

How to reproduce?

  1. Open https://jsfiddle.net/wv3yopo0/139/
  2. Click "Add" button
  3. In the new input type ab
  4. Click "Add" button again
  5. In the new input type cd
  6. Now click the first input and try to edit the value; it doesn't work

screen capture on 2016-05-02 at 13-51-50

Am I missing something?

Most helpful comment

@AriaFallah yes it still matters. MobX doesn't need it, but the React reconciler does need stable keys. Without it React will throw away and recreate your components whole the time. And MobX can't optimize that :)

All 13 comments

@mweststrate @AriaFallah I would appreciate your help on this

@hnordt found the problem

Working fiddle https://jsfiddle.net/wv3yopo0/141/


addTodo needed to be changed to

addTodo() {
  this.todos.push({ text: '' })
}

I think the problem was that you dynamically added a key to a plain object in handleChange, which caused it to not be observed. If the key exists on the object when it's first inserted into the array it works fine.

Also I needed to change:

<li key={`${todo.text}${index}`}>

// to

<li key={index}>

Not sure why you were making the key like that, but it was part of the problem.


The other solution is to use the mobx map to properly be able to dynamically add the key

import { map } from 'mobx'

// addTodo
this.todos.push(map({}))

and in handleChange

todo.set('text', event.target.value)

You are the best @AriaFallah ! Thank you.

About the key part, please read:
https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318

@hnordt ah that key post makes sense, but perhaps you should find something other than text to use there if it's going to break the rerendering.

Yeah, I’ll assign an UID. I used text just for demo purposes.

Em 2 de mai de 2016, à(s) 15:11, Aria Fallah [email protected] escreveu:

@hnordt https://github.com/hnordt ah that key post makes sense, but perhaps you should find something other than text to use there if it's going to break the rerendering.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub https://github.com/mobxjs/mobx/issues/231#issuecomment-216314656

@hnordt actually after thinking about it...does it matter what the key is when you're using MobX? MobX will rerender the component whenever there is a change regardless of what React thinks has changed.

That way key={index} is not an antipattern with MobX.

I don’t know.

Anyway as a best practice I’ll always set an unique key.

Em 2 de mai de 2016, à(s) 15:31, Aria Fallah [email protected] escreveu:

@hnordt https://github.com/hnordt actually after thinking about it...does it matter what the key is when you're using MobX? MobX will rerender the component whenever there is a change regardless of what React thinks has changed.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub https://github.com/mobxjs/mobx/issues/231#issuecomment-216320705

@AriaFallah yes it still matters. MobX doesn't need it, but the React reconciler does need stable keys. Without it React will throw away and recreate your components whole the time. And MobX can't optimize that :)

@AriaFallah

We use map for dynamic observables.

So why not always use map? The main reason is that const obs = map({ hello: 'world' }) is slower than const obs = observable({ hello: 'world' })?

@hnordt maybe you can best compare it with Java; use maps if you have a dynamically keyed collection with uniform values. Use objects for anything with (roughly) predefined attributes.

Thank you @mweststrate, unfortunately I don't know Java and your explanation doesn't helped me 😞

@hnordt

To me the difference isn't necessarily about speed, but about API, semantics, and level of observability.

When you create an observable object, its keys are constant. You're saying that it is a normal object with all the keys it ever needs. Its values can change and be observed, but you're never going add or remove keys from it, want to observe the adding and removing of keys, or want to observe the changes in the newly added keys. Even if you tried to observe these things, it wouldn't work.

With map there are now three differences I have noticed.

  1. Difference in API. You cannot use it like a regular object. Instead you must use .get() and .set()
  2. Difference in meaning. You are saying that the keys inside of it are not constant. They will dynamically be added and removed.
  3. Difference in level of observability. The main thing is that you can observe the adding and removing of keys, and observe the new keys after they have been added. Also this one isn't really apparent in the docs, but it is easier to report an entire MobX map as observed inside an autorun or computed because of the .toJs function. With an observable object, it's much harder to observe the whole entire thing recursively because of MobX being smart about what it observes.

Anything else you'd like to add @mweststrate? Also regarding the last thing I said about .toJs in my 3rd point, is there a good way to recursively report all keys in an ObservableObject type as observed? For me, I came across the problem when using JSON.stringify(obj)inside of an autorun, and it wasn't working.

Thank you @AriaFallah 👍

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mweststrate picture mweststrate  ·  75Comments

Kukkimonsuta picture Kukkimonsuta  ·  65Comments

FouMez picture FouMez  ·  31Comments

arackaf picture arackaf  ·  29Comments

fibric picture fibric  ·  37Comments