使用redux-form我在键入第一个字符后失去焦点

Gre*_*egg 17 validation reactjs redux redux-form

我正在使用redux-form模糊验证.在我将第一个字符输入到输入元素后,它会失去焦点,我必须再次单击它才能继续输入.它只对第一个字符执行此操作.后续字符类型仍然是焦点.这是我的基本签到形式示例:

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);
Run Code Online (Sandbox Code Playgroud)

ris*_*ott 30

发生这种情况是因为您renderField每次渲染时都将其重新定义为新组件,这意味着它看起来像是React 的组件,因此它将卸载原始组件并重新安装新组件.

你需要提升它:

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>
    );
  }
}

...
Run Code Online (Sandbox Code Playgroud)


Abd*_*UMI 7

正如@riscarrott 提到的,放在renderField组件类之外。

但我仍然失去焦点.. 经过测试,我得出结论,由于使用了柯里化函数(返回另一个函数,而不是直接返回元素。),重新渲染完成。

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>
    );
Run Code Online (Sandbox Code Playgroud)

然后,如果您renderField是咖喱函数:

然后,不要这样做:

     //.....

     <Field name="email" type="text" component={renderField('input')} label="Email Address" />
     <Field name="desc" component={renderField('textarea')} label="Email Address" />
Run Code Online (Sandbox Code Playgroud)

但是,请执行以下操作:

  // 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" />
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好解释的答案,可能为我节省了几个小时。谢谢@abdennour! (2认同)