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

Posted

技术标签:

【中文标题】使用 redux-form 输入第一个字符后我失去了焦点【英文标题】:Using redux-form I'm losing focus after typing the first character 【发布时间】:2017-02-11 20:06:08 【问题描述】:

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

【问题讨论】:

【参考方案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

以上是关于使用 redux-form 输入第一个字符后我失去了焦点的主要内容,如果未能解决你的问题,请参考以下文章

异步验证后的 Redux-Form 文件上传

使用 redux-form 和 react-select.creatable 为啥模糊事件会清除输入?

如何将 redux-form 绑定连接到表单的输入

输入字段失去对每个字符类型的关注 - 反应

在 React、Redux-Form 和 GraphQL 中选择输入中的 onChange 事件从数据库中查询

React - 以动态形式输入 1 个字符后输入失去焦点