Search code examples
mobxmobx-reactmobx-state-treemobx-react-form

How to bind mobx-react-form with mobx-state-tree store


I have a form with three fields A, B and C. I am using mobx-react-form to handle the fields because it comes with onChange updates and validation baked in. I have set this up and it's working fine when I log out the values.

const View = inject('store')(observer(({ title }: Props) => {
  return (
    <div>
      <form onSubmit={form.onSubmit}>
        <label htmlFor={form.$('A').id}>
          {form.$('A').label}
        </label>
        <input {...form.$('A').bind()} />

        <label htmlFor={form.$('B').id}>
          {form.$('B').label}
        </label>
        <input {...form.$('B').bind()} />

        <label htmlFor={form.$('C').id}>
          {form.$('C').label}
        </label>
        <input {...form.$('C').bind()} />

        <button type="submit" onClick={form.onSubmit}>
          Submit
       </button>
      </form>
    </div>
  );
}));

I will use the values from fields A, B and C to calculate additional values D and E which will appear in the app.

For state management, I am using mobx-state-tree to create the store.

export const Store = types.model('Store', 
{
  A: types.maybeNull(types.number),
  B: types.maybeNull(types.number),
  C: types.maybeNull(types.number),
  D: types.maybeNull(types.number),
  E: types.maybeNull(types.number),
})
  .views(self => {
    return { 
      getD: () => self.D,
      getE: () => self.E 
    };
  })
  .actions(self => {
    return {
      setD: (A, B) => self.D = A + B,
      setE: (B, C) => self.E = C - B,
      resetStore: () => {
        self.A = defaultState.A;
        self.B = defaultState.B;
        self.C = defaultState.C;
        self.D = defaultState.D;
        self.E = defaultState.E;
      },
    };
  });

How can I bind the mobx-react-form fields A, B and C to corresponding values in the store so they update on change?


Solution

  • Well,

    first of all, I want you to notice , you are trying to connect 2 different state managers .

    I like mobx-recat-form very much ! but you should consider that it manages the state for you automatically .

    You can bind yourself to onChange, and update D,E accordingly .

    For Example:

    <input onChange={e => {
       form.$('B').set(e.target.value);
       // handle D,E according to value
    }} />
    

    this is the most "direct" way to deal with it. if you want to solve it in more "mobx" way ,

    Do something likes this:

    form.$('B')
       .observe(({ form, field, change }) => { 
         // deal with D,E according to values
       });
    

    For further information I would take a look into: https://foxhound87.github.io/mobx-react-form/docs/extra/mobx-events.html

    And I would suggest to stick with this library(mobx-react-form) for controlling the forms , and with direct hooks(1 st example) or by observing the form propagate changes to other values in other stores .