如何从formik形式与其他字段反应FieldArray中获取值?

时间:2019-10-01 19:50:43

标签: reactjs formik

我创建了一个Formik表单,其中包含一个字段数组,表单,并且fieldArray在两个单独的类中作为单独的组件。

我的表单:

<Formik onSubmit = {(values, { setSubmitting }) => { setSubmitting(false);}}
        enableReinitialize>
    {({handleSubmit, errors})=> (
        <Form onSubmit= { handleSubmit }>
            <Form.Group as= { Row } controlId= "cpFormGroupTitle" className="required">
                <Form.Label className="post-create-label"  column sm={ 2 } >
                    Title
                </Form.Label>
                <Col sm={ 10 }>
                    <Field name="title" component={ renderTextField } type="text"
                           isinvalid={ !!errors.title ? "true": "false" }
                           placeholder="Title *" />
                </Col>
            </Form.Group>
            <Form.Group as= { Row } controlId= "cpFrmGroupShortDesc"  className="required">
                <Form.Label className="post-create-label"  column sm={ 2 } >
                    Short Description
                </Form.Label>
                <Col sm={ 10 }>
                    <Field name="short-desc" component={ renderTextArea } type="text"
                           isinvalid={ !!errors.shortDescription ? "true": "false" }
                           placeholder="Short Description *" />
                </Col>
            </Form.Group>
            <Form.Group as= { Row } controlId= "cpFormGroupFeatures">
                <Form.Label className="post-create-label"  column sm={ 2 }>
                    Features
                </Form.Label>
                <Col sm={ 10 }>
                    <TextFieldArray initialValues={{ features: [] } } name="features"/>
                </Col>
            </Form.Group>
            <Form.Group as={ Row }>
                <Col sm= { { span: 2, offset:2 } }>
                    <Button type="submit"  variant="primary">Submit</Button>
                </Col>
                <Col sm={ 2 }>
                    <Button variant="secondary">Save as draft</Button>
                </Col>
            </Form.Group>
        </Form>
    )}
</Formik>

这里,<TextFieldArray>是字段数组,提交表单后,我需要从字段数组获取值。

TextFieldArray:

export const TextFieldArray = (props) => (
    <React.Fragment>
        <Formik initialValues= { props.initialValues } render={({ values }) => (
            <Form>
                <FieldArray name= { props.name } render={arrayHelper => (
                    <div>
                        { values[props.name] && values[props.name].length > 0 ?
                            (
                                values[props.name].map((item, index) => (
                                    <div key={index}>
                                        <Form.Group as= { Row }>
                                            <div className="col-md-8">
                                                <Field name={`${props.name}.${index}`}
                                                       className="form-control"/>
                                            </div>
                                            <div className="col-md-2">
                                                <Button type="button" variant="outline-secondary"
                                                        onClick={() => arrayHelper.remove(index)}>
                                                    Remove
                                                </Button>
                                            </div>
                                            <div className="col-md-2">
                                                <Button type="button" variant="outline-secondary"
                                                    onClick={() => arrayHelper.insert(index, '')}>
                                                    Add
                                                </Button>
                                            </div>
                                        </Form.Group>
                                    </div>
                                ))
                            ) : (
                                <Button type="button" variant="outline-secondary"
                                        onClick={() => arrayHelper.push('')} >
                                   {`Add ${ props.name }`}
                                </Button>
                            )
                        }
                    </div>
                )} />
            </Form>
        )} />
    </React.Fragment>
);

我是ReactJS的初学者,所以请有人帮助我,这将对大家有很大帮助。 谢谢。

2 个答案:

答案 0 :(得分:0)

我认为您不需要为子组件创建第二种形式。
您只需将值从父级传递到TextFieldArray

    <TextFieldArray values={values.myArr} name="features"/>     

子组件仅接收值并呈现它们(就像它在父组件中一样)

export const TextFieldArray = (props) => {
return (
    <React.Fragment>
                    <FieldArray
                        name= { props.name }
                        render={arrayHelper => (
                            <div>
                                {
                                    props.values[props.name] && props.values[props.name].length > 0 ?
                                        (
                                            props.values[props.name].map((item, index) => (
                                                <div key={index}>
                                                    <Form.Group as= { Row }>
                                                        <div className="col-md-8">
                                                            <Field name={`${props.name}.${index}`} className="form-control"/>
                                                        </div>
                                                        <div className="col-md-2">
                                                            <Button type="button" variant="outline-secondary"
                                                                onClick={() => arrayHelper.remove(index)}>
                                                                Remove
                                                            </Button>                                                              
                                                        </div>
                                                        <div className="col-md-2">
                                                            <Button type="button" variant="outline-secondary"
                                                                onClick={() => arrayHelper.insert(index, '')}
                                                            >
                                                                Add
                                                            </Button> 
                                                        </div>
                                                    </Form.Group>
                                                </div>
                                            ))
                                        ) : (
                                            <Button type="button" variant="outline-secondary" onClick={() => arrayHelper.push('')} >
                                               {`Add ${ props.name }`}
                                            </Button>
                                        )
                                }
                            </div>
                        )}
                    />
    </React.Fragment>
)

当然不要忘记将数组的初始值添加到父组件中。

最后,当您单击“提交”按钮时,它将为您提供值。

答案 1 :(得分:0)

要使字段数组与其他字段具有相同的形式,请仅包含一个<Formik>和一个<Form>。然后在Formik上创建用于描述所有字段的initialValues:

<Formik
  initialValues={{ friends: someFriends, random: randomText }}

如以下Formik FieldArray文档中的代码所示,添加了另一个不属于数组的表单字段:

import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Formik, Form, Field, useField, FieldArray } from "formik";

const someFriends = ["jared", "ian", "brent"];
const randomText = "Four score and seven years ago...";

function MyTextInput({ label, ...props }) {
  // useField() returns [formik.getFieldProps(), formik.getFieldMeta()]
  // which we can spread on <input> and alse replace ErrorMessage entirely.
  const [field, meta] = useField(props);
  return (
    <>
      <label
        htmlFor={props.id || props.name}
        css={{ backgroundColor: props.backgroundColor }}
      >
        {label}
      </label>
      <input className="text-input" {...field} type="text" {...props} />
      {meta.touched && meta.error ? (
        <div className="error">{meta.error}</div>
      ) : null}
    </>
  );
}

// Here is an example of a form with an editable list.
// Next to each input are buttons for insert and remove.
// If the list is empty, there is a button to add an item.
export const FriendList = () => (
  <div>
    <h1>Friend List</h1>
    <Formik
      initialValues={{ friends: someFriends, random: randomText }}
      onSubmit={values =>
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
        }, 500)
      }
      render={({ values }) => (
        <Form>
          <MyTextInput label="Random comment" name="random" />
          <FieldArray
            name="friends"
            render={arrayHelpers => (
              <div>
                {values.friends &&
                  values.friends.length > 0 &&
                  values.friends.map((friend, index) => (
                    <div key={index}>
                      <Field name={`friends.${index}`} />
                      <button
                        type="button"
                        onClick={() => arrayHelpers.remove(index)} // remove a friend from the list
                      >
                        -
                      </button>
                      <button
                        type="button"
                        onClick={() => arrayHelpers.insert(index, "")} // insert an empty string at a position
                      >
                        +
                      </button>
                    </div>
                  ))}

                {/* Add a new empty item at the end of the list */}
                <button type="button" onClick={() => arrayHelpers.push("")}>
                  Add Friend
                </button>

                <div>
                  <button type="submit">Submit</button>
                </div>
              </div>
            )}
          />
        </Form>
      )}
    />
  </div>
);

ReactDOM.render(<FriendList />, document.getElementById("root"));

Code in codesandbox