monkeyjumps monkeyjumps - 4 years ago 144
Javascript Question

Using ReactJs, How do I update my form fields when my parent object sent in from props changes?

I am using REactJs to dynamically create some form fields. these form fields are mapped to a document object. Visually it is a three column app. A document queue displayed on left with many clickable document icons , fields in the middle and the document image on the right. There can be multiple documents. Each document has fields associated to it. If a user inputs values into the fields then clicks another document. I want the input fields to be reset for the new document or saved values loaded.

Below is the last attempt i tried where I am using the DefaultValue attribute; i've tried to pass the values in from a function. I ve also tried value attribute but that locks the value not allowing the user to change it.

Currently I successfully save the state of the document queue and its fields but i just cannot get the UI to reflect my state object: documentQueue.

I ve read where people suggest using value={state} but that doesn't quite work for my state object. My forms are more dynamic and complex.

var Fields = React.createClass({
getInitialState: function () {
return {
currentDocumentIndex: 0,
shouldUpdate: false,
randomKey : 0
};
},
componentWillReceiveProps: function (nextProps) {
console.log("compare props");
console.log(nextProps.fields === this.props.fields);
var forceRender = !(nextProps.fields === this.props.fields);
//only change state if needed.
if (forceRender) {
if (!this.state.shouldUpdate) {
this.setState({ shouldUpdate: true ,randomKey : Math.random() }, function () {
console.log("should update fields state set");
console.log(this.state.shouldUpdate);
});
}
} else {
if (this.state.shouldUpdate) {
this.setState({ shouldUpdate: false , randomKey: Math.random() }, function () {
console.log("should update fields state set");
console.log(this.state.shouldUpdate);
});
}
}
},
getDataType: function (datatype, fieldId) {
switch (datatype) {
case 0:
case 1:
case 2:
case 3:
case 4:
return <div class="col-sm-6"><input type="text" key={this.state.randomKey+1} className="form-control" id={fieldId} onChange={this.onValueChanged.bind(this)} value={this.props.fields[fieldId]} /></div>
case 5:
return <div class="col-sm-6"><input type="text" key={this.state.randomKey+2} className="form-control" id={fieldId} onChange={this.onValueChanged.bind(this)} /></div>
case 6:
return <div class="col-sm-6"><input type="checkbox" key={this.state.randomKey+3} className="form-control" id={fieldId} value="true" onChange={this.onChecked.bind(this)} /></div>
case 7:
return <div class="col-sm-6"><textarea type="text" rows="5" key={this.state.randomKey+4} className="form-control" id={fieldId} onChange={this.onValueChanged.bind(this)} ></textarea></div>
}
},
onChecked : function(event){
},
onValueChanged : function(event){
this.props.onFieldChange(this.props.currentDocumentIndex, event.target.id, event.target.value);
},
renderFields: function () {
var fieldNames = [];
if (this.props.doctype == null) {
console.log("fields are null");
} else {
console.log("fields are valid from Field component");
for (var index = 0; index < this.props.doctype.Fields.length; index++)
{
var inputField = this.getDataType(this.props.doctype.Fields[index].DataType, this.props.doctype.Fields[index].DocumentTypeFieldID);
fieldNames.push(<label className="control-label col-sm-6">{this.props.doctype.Fields[index].Name}</label>);
fieldNames.push(inputField);
}
}
return (
<form className="form-horizontal" role="form">
<div className="form-group">
{fieldNames}
</div>
</form>
);
},
render: function () {
return (
<div>
{this.renderFields()}
</div>
);
}


});

Answer Source

If you want to manage an input value with React, you can use the value prop.

However, as you've seen, the user can no longer directly edit the field.

To allow user edits, you must also set onChange on the field and write the incoming edits somewhere such as state.

The docs for ReactLink have a good example of this:

var NoLink = React.createClass({
  getInitialState: function() {
    return {message: 'Hello!'};
  },
  handleChange: function(event) {
    this.setState({message: event.target.value});
  },
  render: function() {
    var message = this.state.message;
    return <input type="text" value={message} onChange={this.handleChange} />;
  }
});

Also, you may just want to use ReactLink.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download