【问题标题】:Using redux-form I'm losing focus after typing the first character使用 redux-form 输入第一个字符后我失去了焦点
【发布时间】:2023-03-20 12:07:01
【问题描述】:

我正在使用 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);

【问题讨论】:

    标签: validation reactjs redux redux-form


    【解决方案1】:

    其实这是函数组件的问题。我使用了基于类的组件和 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);
    

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            【解决方案5】:

            对我有用的是将 arrowFunction-based 组件重构为 class-based 组件,因为 InputForm 组件的行为很奇怪。每次更改每个输入的值时,即使将每个 inputType 拆分为单独的组件,它们也会重新渲染。除了将主要组件更改为基于类之外,别无其他需要解决的问题。我猜可能是 redux-form 本身造成的。

            【讨论】:

              【解决方案6】:

              我遇到了同样的问题。当我将我的 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;
              }

              【讨论】:

                【解决方案7】:

                发生这种情况是因为您每次渲染时都将 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>
                    );
                  }
                }
                
                ...
                

                【讨论】:

                • 噢!谢谢。我会试试看的。
                • 谢谢,这对我有用,即使是功能组件。
                【解决方案8】:

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

                但我仍然失去焦点..经过测试,我得出结论,重新渲染是因为使用 curried 函数(返回另一个函数,而不是直接返回元素。)

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

                那么,如果你的 renderField 是一个柯里化函数:

                那么,不要做????:

                     //.....
                
                     <Field name="email" type="text" component={renderField('input')} label="Email Address" />
                     <Field name="desc" component={renderField('textarea')} label="Email Address" />
                

                但是,请执行以下操作????:

                  // 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" />
                

                【讨论】:

                • 这是一个很好解释的答案,可能为我节省了几个小时。谢谢@abdennour!
                • 欢迎@rakitin
                猜你喜欢
                • 1970-01-01
                • 2021-10-27
                • 2019-12-19
                • 1970-01-01
                • 2021-12-14
                • 2020-06-03
                • 1970-01-01
                • 2022-01-16
                相关资源
                最近更新 更多