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

时间:2016-10-03 19:31:02

标签: 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);

7 个答案:

答案 0 :(得分:21)

这是因为您每次渲染时都将renderField重新定义为新组件,这意味着它看起来像是一个组件,因此它将卸载原始组件并重新安装新的。

你需要提升它:

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

...

答案 1 :(得分:1)

对我有用的是,将InputForm组件的行为怪异地将基于 arrowFunction-based 的组件重构为基于基于类的的组件。每次更改每个输入的值时,即使将每个inputType拆分为单独的组件,它们也会全部重新呈现。除了将主要组件更改为基于类的内容外,没有其他任何要修复的内容。我猜可能是 redux-form 本身引起的。

答案 2 :(得分:0)

我有同样的问题。当我将我的React Redux表单添加到createForms()中的商店时,我解决了这个问题:

export const ConfigureStore = () => {
  const store = createStore(
    combineReducers({

      tasks: Tasks,
      task: Task,
      image: Image,
      admin: Admin,
      pageId: PageID,
      fieldValues: FieldValues,
      formValues: FormValues,

      ...createForms({
        createTask: initialTask,
        editTask: initialEditTask
      })
    }),
    applyMiddleware(thunk, logger)
  );

  return store;
}

答案 3 :(得分:0)

如果在渲染函数中定义了样式组件,也会发生这种情况。 您应该在课堂之外定义它们。 像这样:

const Row = styled.div`
    justify-content:center;
`;
const Card = styled.div`
    width:18rem;
    padding:1rem;
 `;
 class Login extends Component{

答案 4 :(得分:0)

我有同样的问题。我通过将组件更改为Class组件解决了我的问题,并从render()中删除了所有css样式配置。

答案 5 :(得分:0)

我遇到了同样的问题,没有答案对我有用。 但是多亏Advem的回答,我才知道可能出什么问题了: 我的表单需要手风琴UI,为此我要有状态变量

const ConveyorNotificationSettingsForm = (props) => {
    const {handleSubmit, formValues, dirty, reset, submitting} = props;
    const [expandedSection, setExpandedSection] = useState(null);
...

只有一个扩展部分,其索引等于expandedSection

我将手风琴提取到一个单独的功能组件并将useState移到那里之后,问题就消失了。

答案 6 :(得分:0)

其实这是功能组件的问题。我使用了一个带有 redux 形式的基于类的组件,我的问题解决了。我不知道确切的原因,但是当我们输入第一个单词和损失焦点时,redux 表单会重新呈现。每当您想使用 redux 表单时,请使用基于类的组件。

class StreamCreate extends React.Component{
rendorInput(formProps){
    return <input {...formProps.input} />; 
}

render(){
    return (
        <Container maxWidth="lg">
            <form action="">
                <Field name="title" component={this.rendorInput}/>
                <Field name="description" component={this.rendorInput} />
            </form>
        </Container>       
    )
}

}

export default reduxForm({
    form: 'createStream'
})( StreamCreate);