Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using redux-form I'm losing focus after typing the first character

I'm using redux-form and on blur validation. After I type the first character into an input element, it loses focus and I have to click in it again to continue typing. It only does this with the first character. Subsequent characters types remains focuses. Here's my basic sign in form example:

import React, { Component } from 'react'; import { connect } from 'react-redux'; import { Field, reduxForm } from 'redux-form'; import * as actions from '../actions/authActions';  require('../../styles/signin.scss');   class SignIn extends Component {    handleFormSubmit({ email, password }) {     this.props.signinUser({ email, password }, this.props.location);   }    renderAlert() {     if (this.props.errorMessage) {       return (         <div className="alert alert-danger">           {this.props.errorMessage}         </div>       );     } else if (this.props.location.query.error) {       return (         <div className="alert alert-danger">           Authorization required!         </div>       );     }   }    render() {      const { message, handleSubmit, prestine, reset, submitting } = this.props;      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>     );       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>     );   } }  function validate(values) {   const errors = {};    if (!values.email) {     errors.email = 'Enter a username';   }    if (!values.password) {     errors.password = 'Enter a password'   }    return errors; }  function mapStateToProps(state) {   return { errorMessage: state.auth.error } }  SignIn = reduxForm({   form: 'signin',   validate: validate })(SignIn);  export default connect(mapStateToProps, actions)(SignIn); 
like image 382
Gregg Avatar asked Oct 03 '16 19:10

Gregg


People also ask

Why does the input field lose focus after typing a character?

it is because you are rendering the form in a function inside render(). Every time your state/prop change, the function returns a new form. it caused you to lose focus. Try putting what's inside the function into your render directly.

Is Redux form good?

Redux-form is a really great library for working with validations. You can simply develop a lot of validations for different situations. Hence it provides validation functions to validate all the values in your form at once. You may also provide individual value validation functions for each Field or FieldArray.

How do I initialize a Redux form?

To get those values into your redux-form -decorated component, you will need to connect() to the Redux state yourself and map from the data reducer to the initialValues prop. By default, you may only initialize a form component once via initialValues .


1 Answers

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>     );   } }  ... 
like image 163
riscarrott Avatar answered Oct 14 '22 23:10

riscarrott