Ad

React Components State Vs Props Dynamic Input

- 1 answer

I have been experimenting couple of days with ReactJS and ES6 and created couple of components i.e. <InputText />, <InputNumber />, <InputEmail />, that are being used in the component <ContactsEdit />.

It seems really strange that even though I have read many tutorials my child components refuse to render() the {this.state.Firstname} even though I tried componentWillMount, componentDidMount, this.setState, this.state with this.forceUpdate(), but they will render fine the this.props.Firstname

I would welcome any kind of suggestions or help. The source can be found at github

Thanks :)

` export default class ContactsEdit extends React.Component {

constructor(props) {
    super(props);

    this.contactId = this.props.params.id;
    this.persistence = new Persistence('mock');

    this.state = {
        contact : {}
    };

}

componentDidMount() {
    this.persistence.getContactById( this.contactId ).then( (resolve) => {
        this.setState({ contact : resolve.data });
        this.data = resolve.data;
    }).catch( (reject) => {
        console.log(reject);
    }) ;

    this.forceUpdate();
}

onChange(id,newValue)  {
    this.state.contact[ id ] = newValue;
    this.forceUpdate();
}

saveRecord( object ) {
    console.log( this.state );
}

render() {
    return (            
        <div className="ContactsEdit">
            <h2>Contact Edit (Parent) id : {this.props.params.id}, FullName : {this.state.contact.Firstname} {this.state.contact.Lastname}</h2>
            <div className="row">                    
                <InputText id="Firstname" fieldName={this.state.contact.Firstname}  labelName="Firstname" onChange={this.onChange.bind(this)} divClass="col-lg-3 col-md-3 col-sm-3 col-xs-6" />
                <InputText id="Lastname"  fieldName={this.state.contact.Lastname}  labelName="Lastname"  onChange={this.onChange.bind(this)} divClass="col-lg-3 col-md-3 col-sm-3 col-xs-6" />
                <InputText id="SocSecId"  fieldName={this.state.contact.SocSecId}  labelName="SocSecId"  onChange={this.onChange.bind(this)} divClass="col-lg-3 col-md-3 col-sm-3 col-xs-6" />
                <InputText id="DriverLicId"  fieldName={this.state.contact.DriverLicId}  labelName="DriverLicId"  onChange={this.onChange.bind(this)} divClass="col-lg-3 col-md-3 col-sm-3 col-xs-6" />
            </div>

        </div>
    )
}

}

`

` export default class InputText extends React.Component {

constructor(props) {
    super(props);         
    this.state = { fieldName : this.props.fieldname}; 
}

componentWillMount() {
    //this.state.fieldName = this.props.fieldname;
    //this.forceUpdate();
}

updateState(evt) {
    //this.setState( {fieldName : evt.target.value} );
    this.props.onChange( evt.target.id, evt.target.value     );
}

render() {
    return (
        <div className={this.props.divClass}>
            <hr />
            <label> {this.props.labelName} </label>
            <div>{this.props.fieldName}</div> 
            <div>{this.state.fieldName}</div> 
            <input 
                type="text" 
                id={this.props.id} 
                value={this.props.fieldName} 
                onChange={this.updateState.bind(this)} 
                className="form-control"
            />
        </div>
    )
}

} `

Ad

Answer

this.props doesn't exist in the constructor function until after its run, binding this to an instance of the class. Use the props that are passed in from the parent (in the argument)

constructor (props) {
    super(props)
    this.state = { fieldName: props.fieldname }
}

componentWillMount is replaced by using ES6 class constructor

Also you should not modify this.state directly. It won't cause react to call render(). Only set the initial state in constructor. Everywhere else, call this.setState({ data: newData }).

Ad
source: stackoverflow.com
Ad