Best practice for ReactJS form components Best practice for ReactJS form components reactjs reactjs

Best practice for ReactJS form components


  1. Anything that is going to change goes in State.
  2. If you're looking at loading an existing entity and editing it, you want controlled inputs, and you want to set the values accordingly. I tend to stay away from defaultValue in most cases (outside of dropdowns)
  3. This ties back in to your previous question. If you specify a value, you are using a controlled input, and you have to provide an onChange handler for any controlled input, otherwise it is set in stone. A benefit of controlled inputs is that users can't edit them, so if you had some properties locked down (maybe for read only, security reasons), when the user attempts to save, even if they edited the HTML directly, React should pull the property's value from the vDOM representation (could be wrong here, but I believe I've tested this before). Anyway, you have to have onChange set directly on controlled inputs. As far as using event delgation (at the form level), this isn't a bad practice at all for a lot of events, this is just a specific scenario (controlled inputs) where you need onChange events specified for each element.
  4. Not entirely sure what the ask on this one is, but I used refs instead of target.name.
  5. So, you're correct in that you should never alter the state directly, and this is a tricky bit from the docs. React is going to alter state directly, it's just going to do it in the implementation through setState. If you alter state outside of this method call, unexpected things will happen and errors will be thrown.

shouldComponentUpdate only does shallow comparisons, but there are a few solutions here.

One is to stringify the objects, this is a quick and dirty object comparison, don't really recommend it, but it works.

A better solution, and one I have used with React + Flux is to implement a propertyChanged bool, and just check that in your shouldComponentUpdate.

Now, this will require you to be aware of setting it when things change, i.e., you changed something deeper in the object graph. Say propertyOne is an object with a property that gets changed in your handleChange method. You would validate the input however you wish, then set propertyChanged = true, and you then need to implement componentDidUpdate. We're making an assumption here, but if the component has updated, you set propertyChanged back to false so you don't have any further triggering of unwanted updates. I hope that makes sense. It's kinda like a one-way notifyPropertyChanged.

I'm providing a quick example of what I would probably do for a more dynamic implementation that allows you to add more properties to your object (only shallow properties in this implementation, obviously you could write a more robust solution). Let me know if you have any further questions or if I didn't answer something.

http://jsfiddle.net/rpv9trhh/

var e = {    prop1: 'test',    prop2: 'wee',    prop3: 'another property',    propFour: 'Oh yeah!'};var FormComp = React.createClass({    getInitialState: function(){        return {            entity: this.props.entity        }    },    render: function() {        var ent = this.state.entity;        var that = this;        var inputs = [];        for(var key in ent){            inputs.push(<input                key={key}                style={{display:'block'}}                type="text"                ref={key} onChange={that._propertyChanged.bind(null, key)}               value={ent[key]} />)        }        return <form>            {inputs}            <input                 type="button"                 onClick={this._saveChanges}                 value="Save Changes" />        </form>;    },    _propertyChanged: function(propName) {        var nextProp = this.refs[propName].getDOMNode().value;        var nextEntity = this.state.entity;        nextEntity[propName] = nextProp;        this.setState({            entity: nextEntity        });    },    _saveChanges: function() {        var updatedEntity = this.state.entity;        for(var key in updatedEntity){            alert(updatedEntity[key]);        }        //TODO: Call to service to save the entity, i.e.            ActionCreators.saveEntity(updatedEntity);    }});React.renderComponent(<FormComp entity={e} />, document.body);