【问题标题】:How do I use types defined by @types/redux-form in React component with Field and FieldArray?如何在带有 Field 和 FieldArray 的 React 组件中使用 @types/redux-form 定义的类型?
【发布时间】:2018-09-19 19:16:54
【问题描述】:

我正在使用 React、Redux、Redux-Form 和 TypeScript 开发应用程序。我正在努力使用包 @types/redux-form (DefinitelyTyped) 定义的类型,尤其是使用 FieldArray。有一个属性“组件”,我在其中传递对组件的引用,但我不知道在描述它的道具时应该使用什么类型。我从Redux-Form repository 下载了使用 FieldArray 的示例,并对其稍作修改以使用 TypeScript。我想用 compilerOption "noImplicitAny": true 编译它。所以这里是FieldArraysForm.tsx(类似于official example):

import * as React from 'react';
import { Field, FieldArray, reduxForm } from 'redux-form';
import validate from './validate';

const renderField = (props) => {
  const { touched, error } = props.meta;
  const { input, label, type } = props;

  return (
    <div>
      <label>{label}</label>
      <div>
        <input {...input} type={type} placeholder={label} />
        {touched && error && <span>{error}</span>}
      </div>
    </div>
  )
}

const renderHobbies = (props) => {
  const { fields } = props;
  const { error } = props.meta;
  return (
    <ul>
      <li>
        <button type="button" onClick={() => fields.push()}>
          Add Hobby
        </button>
      </li>
      {fields.map((hobby, index) => (
        <li key={index}>
          <button
            type="button"
            title="Remove Hobby"
            onClick={() => fields.remove(index)}
          />
          <Field
            name={hobby}
            type="text"
            component={renderField}
            label={`Hobby #${index + 1}`}
          />
        </li>
      ))}
      {error && <li className="error">{error}</li>}
    </ul>
  )
}

const renderMembers = (props) => {
  const { fields } = props;
  const { error, submitFailed } = props.meta;

  return (
    <ul>
      <li>
        <button type="button" onClick={() => fields.push({})}>
          Add Member
        </button>
        {submitFailed && error && <span>{error}</span>}
      </li>
      {fields.map((member, index) => (
        <li key={index}>
          <button
            type="button"
            title="Remove Member"
            onClick={() => fields.remove(index)}
          />
          <h4>Member #{index + 1}</h4>
          <Field
            name={`${member}.firstName`}
            type="text"
            component={renderField}
            label="First Name"
          />
          <Field
            name={`${member}.lastName`}
            type="text"
            component={renderField}
            label="Last Name"
          />
          <FieldArray name={`${member}.hobbies`} component={renderHobbies} />
        </li>
      ))}
    </ul>
  )
}

const FieldArraysForm = props => {
  const { handleSubmit, pristine, reset, submitting } = props
  return (
    <form onSubmit={handleSubmit}>
      <Field
        name="clubName"
        type="text"
        component={renderField}
        label="Club Name"
      />
      <FieldArray name="members" component={renderMembers} />
      <div>
        <button type="submit" disabled={submitting}>
          Submit
        </button>
        <button type="button" disabled={pristine || submitting} onClick={reset}>
          Clear Values
        </button>
      </div>
    </form>
  )
}

export default reduxForm({
  form: 'fieldArrays', // a unique identifier for this form
  validate
})(FieldArraysForm)

如何使它与类型一起使用?

【问题讨论】:

    标签: reactjs typescript redux redux-form definitelytyped


    【解决方案1】:

    我找到了解决方案。如果有人和我有同样的问题,我会留下答案。

    import * as React from 'react';
    import { Field, FieldArray, reduxForm, WrappedFieldProps, WrappedFieldArrayProps, InjectedFormProps, GenericFieldArray } from 'redux-form';
    import validate from './validate';
    
    interface CustomFieldProps {
      type?: string;
    }
    
    const FieldArrayCustom = FieldArray as new () => GenericFieldArray<Field, any>;
    
    const renderField = (props: WrappedFieldProps & CustomFieldProps) => {
      const { touched, error } = props.meta;
      const { input, label, type } = props;
    
      return (
        <div>
          <label>{label}</label>
          <div>
            <input {...input} type={type} placeholder={label} />
            {touched && error && <span>{error}</span>}
          </div>
        </div>
      )
    }
    
    const renderHobbies = (props: WrappedFieldArrayProps<undefined>) => {
      const { fields } = props;
      const { error } = props.meta;
    
      return (
        <ul>
          <li>
            <button type="button" onClick={() => fields.push(undefined)}>
              Add Hobby
            </button>
          </li>
          {fields.map((hobby, index) => (
            <li key={index}>
              <button
                type="button"
                title="Remove Hobby"
                onClick={() => fields.remove(index)}
              />
              <Field
                name={hobby}
                type="text"
                component={renderField}
                label={`Hobby #${index + 1}`}
              />
            </li>
          ))}
          {error && <li className="error">{error}</li>}
        </ul>
      )
    }
    
    const renderMembers = (props: WrappedFieldArrayProps<{}>) => {
      const { fields } = props;
      const { error, submitFailed } = props.meta;
    
      return (
        <ul>
          <li>
            <button type="button" onClick={() => fields.push({})}>
              Add Member
            </button>
            {submitFailed && error && <span>{error}</span>}
          </li>
          {fields.map((member, index) => (
            <li key={index}>
              <button
                type="button"
                title="Remove Member"
                onClick={() => fields.remove(index)}
              />
              <h4>Member #{index + 1}</h4>
              <Field
                name={`${member}.firstName`}
                type="text"
                component={renderField}
                label="First Name"
              />
              <Field
                name={`${member}.lastName`}
                type="text"
                component={renderField}
                label="Last Name"
              />
              <FieldArrayCustom name={`${member}.hobbies`} component={renderHobbies} />
            </li>
          ))}
        </ul>
      )
    }
    
    const FieldArraysForm = (props: InjectedFormProps) => {
      const { handleSubmit, pristine, reset, submitting } = props
    
      return (
        <form onSubmit={handleSubmit}>
          <Field
            name="clubName"
            type="text"
            component={renderField}
            label="Club Name"
          />
          <FieldArrayCustom name="members" component={renderMembers} />
          <div>
            <button type="submit" disabled={submitting}>
              Submit
            </button>
            <button type="button" disabled={pristine || submitting} onClick={reset}>
              Clear Values
            </button>
          </div>
        </form>
      )
    }
    
    export default reduxForm({
      form: 'fieldArrays', // a unique identifier for this form
      validate
    })(FieldArraysForm)
    

    【讨论】:

    • 解释您的更改,而不是简单地粘贴生成的代码。
    • 解释为什么FieldArrayCustom
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 2018-01-05
    • 2021-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多