Using redux-form I'm losing focus after typing the first character
This happens because you're re-defining renderField
as a new component every time you render which means it looks like a new component to React so it'll unmount the original one and re-mounts the new one.
You'll need to hoist it up:
const renderField = ({ input, label, type, meta: { touched, invalid, error } }) => ( <div class={`form-group ${touched && invalid ? 'has-error' : ''}`}> <label for={label} className="sr-only">{label}</label> <input {...input} placeholder={label} type={type} className="form-control" /> <div class="text-danger"> {touched ? error: ''} </div> </div> );class SignIn extends Component { ... render() { const { message, handleSubmit, prestine, reset, submitting } = this.props; return ( <div className="row"> <div className="col-md-4 col-md-offset-4"> <form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))} className="form-signin"> <h2 className="form-signin-heading"> Please sign in </h2> {this.renderAlert()} <Field name="email" type="text" component={renderField} label="Email Address" /> <Field name="password" type="password" component={renderField} label="Password" /> <button action="submit" className="btn btn-lg btn-primary btn-block">Sign In</button> </form> </div> </div> ); }}...
As @riscarrott mentioned, put renderField
outside of component class .
But I am still losing focus .. And after testing, I concluded the re-rendering is done because of using curried function (return another function, and not return element . directly) .
const const renderField = (InputComponent = 'input') => ({ input, label, type, meta: { touched, invalid, error } }) => ( <div class={`form-group ${touched && invalid ? 'has-error' : ''}`}> <label for={label} className="sr-only">{label}</label> <InputComponent {...input} placeholder={label} type={type} className="form-control" /> <div class="text-danger"> {touched ? error: ''} </div> </div> );
Then, if your renderField
is a curried function :
then , don't do 😔😔😔😔:
//..... <Field name="email" type="text" component={renderField('input')} label="Email Address" /> <Field name="desc" component={renderField('textarea')} label="Email Address" />
But , do the following 🙂🙂🙂🙂 :
// outside component class const InputField = renderField('input'); const TextAreaField = renderField('textarea'); // inside component class <Field name="email" type="text" component={InputField} label="Email Address" /> <Field name="desc" component={TextAreaField} label="Email Address" />
What worked for me was refactoring arrowFunction-based Component to class-based Component as the behavior of InputForm components was weird. Every time the value of each input was changed they all rerendered even after splitting each inputType to separated components. There was nothing else left to fix but changing main component to class-based. I guess it may be caused by redux-form itself.