question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Can't get field to update/recognize changes in controlled form

See original GitHub issue

Problem:

Can’t edit values - they revert to the initial value after every keypress

I’m pulling my hair out on this issue, which should be pretty simple - but I can’t get it to work. Disclaimer: I’m fairly new to react, but am otherwise a capable engineer with over 10 years of experience with many languages/platforms/frameworks, most recently AngularJS.

Stack:

  • mobx-react-form v1.19.2
  • mobx v3.1.0
  • react v15.4.2

Goal: Simple Update Form

I’m using the RFX-Stack as a foundation for my new company’s new site. Our existing code base uses mobx heavily and people like it a lot, and from what I’ve learned, there’s a lot to love…

So, I’m trying to add a simple Details page, with an edit Modal to the boilerplate - which is where I’m meeting the resistance. I’m going to explain the basics and hopefully that points to a quick solution. I’ll fill in details as needed.

I was able to get the field to be editable by setting defaultValue on the fields instead of value, but that gets into the whole “uncontrolled” form issue - and doesn’t seem to be the route I want to take.

Code

Trying to keep this as short as possible - here’s the highlights from the code …

Form Def: post.form.js

export default new PostForm({
  fields: {
    title: {
      label: 'Title',
      rules: 'required|string|between:5,50',
    },
    completed: {
      label: 'Completed',
      value: true,
      rules: 'boolean',
    },
    uuid: {
      rules: 'string',
    },
  },
});

Message Details Container .jsx

render() {
    const { ui, post } = this.props.store;

    const modal = !(postForm && post) ? null : (
      <PostCreateModal
        open={ui.postCreateModal.isOpen}
        item={post.selected}
        form={postForm}
      />
    );

    return (
      <div className="pt5">
        <h3>Message Details { this.props.params.messageId }</h3>
        <PostDetails item={post.selected} />
        { modal }
      </div>
    );
  }

Post Create Modal jsx

This has become quite a mess at this point - this is the “current” state. initForm is called from the constructor, and the item is a mobx observable containing values for {title: 'post title', uuid: '1234-abc...'}

  static initForm(form, item) {
    if (!_.isEmpty(item) && form) {
      debugger; // eslint-disable-line

      form.fields.forEach((field) => {
        console.assert(form.$(field.key) === field, 'Field and Retrieve Field should be the same'); // eslint-disable-line
        field.set('initial', item[field.key]);
        // field.set('defaultValue', item);
        field.set(item[field.key]);
        // field.bind('onChange', this.customOnChange);
        console.log(`Setting "${field.key}" to "${item[field.key]}" -> (${field.value})`); // eslint-disable-line
        console.assert(item[field.key] === field.value, 'Field Values must match asfter init'); // eslint-disable-line
      });

      form.observe({
        path: 'title',
        key: 'value', // can be any field property
        call: ({ formDx, field, change }) => { // eslint-disable-line
          console.log(`Field changed from "${change.oldValue}" to "${change.newValue}"`); // eslint-disable-line
        },
      });
    }
  }

  customOnChange = field => (e, val) => {
    console.log('Handling Event: %o] %s --> %s', e, field.key, val); // eslint-disable-line
    field.set('value', val);
    console.assert(field.value === val, 'Field Value must match new val after change'); // eslint-disable-line
  };

  render() {
    console.log('Rendering Post Create Modal'); // eslint-disable-line
    const { open, form, item } = this.props;

    if (!form) { return <div />; }
    return (
      <Modal
        contentLabel="Create Post Modal"
        isOpen={open}
        onRequestClose={this.handleCloseModal}
        style={styles}
      >
        <div className="m3">
          <h3>{item ? 'Edit' : 'Create'} Post</h3>
          <form>
            <div className="pb3">
              <TextField
                hintText="Title"
                floatingLabelText={form.$('title').label}
                name={form.$('title').name}
                value={form.$('title').value}
                errorText={form.$('title').error}
                onChange={this.customOnChange(form.$('title'))}
              />
            </div>
            <div className="tc">
              <button
                type="submit"
                className={button}
                onClick={form.onSubmit}
              >Save</button>
            </div>
          </form>
        </div>
      </Modal>
    );
  }

Console Logging:

When typing “abc” into the end of the title field, I get the following in the console:

Rendering Post Details for item: Object
Setting "title" to "Internal Markets Technician" -> (Internal Markets Technician)
Setting "uuid" to "5b41f0d2-ac46-4a8c-a7df-99b5e9d5eaf1" -> (5b41f0d2-ac46-4a8c-a7df-99b5e9d5eaf1)
Rendering Post Create Modal
Rendering Post Create Modal
Handling Event: [Proxy] title --> Internal Markets Techniciana
Field changed from "Internal Markets Technician" to "Internal Markets Techniciana"
Handling Event: [Proxy] title --> Internal Markets Technicianb
Field changed from "Internal Markets Technician" to "Internal Markets Technicianb"
Handling Event: [Proxy] title --> Internal Markets Technicianc
Field changed from "Internal Markets Technician" to "Internal Markets Technicianc"

… and no visible change. I thought I’d be able to catch an event (hence the “field change from …” logger message), but I don’t see anything changing it back to the initial value.

So … what am I missing? What stupid mistake am I making?

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
foxhound87commented, Feb 22, 2017

About developing on RFX, I suggest you to use React classes only for containers. Keep the other components as stateless function, pass the props, and leave the mobx flow happen 😄

1reaction
pdfowlercommented, Feb 22, 2017

Thanks for the quick help! That did the trick. I’m planning on packaging up a PR for the rfx-stack to include a basic example to add more CRUD functionality to the baseline. Seems like having a details view + editing functionality fits well into the boilerplate. I’ll ping you with updates shortly from that repo!

Read more comments on GitHub >

github_iconTop Results From Across the Web

How do you update Form from a controlled component? #153
I have a wrapper component that changes default behaviour of how the value is formatted. This component works and updates the value just...
Read more >
Can't type in React input text field - Stack Overflow
In my requirement i wanted to input field with typing enable as well as it needs to be set to default value came...
Read more >
Detect Web Form Field Changes in ASP.NET - CODE Magazine
Step 1: Identify Server Control and Extend Common Interface · Step 2: Hook up Value Change Event Handler · Step 3: Implement Logic...
Read more >
How To Programmatically Add Input Fields to React Forms
Save the changes and preview the application in your browser to see the form. Screenshot of a simple React Form. Controlling the Input...
Read more >
How to Identify Different Inputs with One Onchange Handler
The most common approach is to attach an onChange event to each input field. Whenever the event is triggered, call a separate function...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found