React Formik在<formik>之外使用submitForm

时间:2018-03-28 02:18:25

标签: reactjs formik

当前行为

<Formik
    isInitialValid
    initialValues={{ first_name: 'Test', email: 'test@mail.com' }}
    validate={validate}
    ref={node => (this.form = node)}
    onSubmitCallback={this.onSubmitCallback}
    render={formProps => {
        const fieldProps = { formProps, margin: 'normal', fullWidth: true, };
        const {values} = formProps;
        return (
            <Fragment>
                <form noValidate>
                    <TextField
                        {...fieldProps}
                        required
                        autoFocus
                        value={values.first_name}
                        type="text"
                        name="first_name"

                    />

                    <TextField
                        {...fieldProps}
                        name="last_name"
                        type="text"
                    />

                    <TextField
                        {...fieldProps}
                        required
                        name="email"
                        type="email"
                        value={values.email}

                    />
                </form>
                <Button onClick={this.onClick}>Login</Button>
            </Fragment>
        );
    }}
/>

我正在尝试此解决方案https://github.com/jaredpalmer/formik/issues/73#issuecomment-317169770,但它始终会返回Uncaught TypeError: _this.props.onSubmit is not a function

当我尝试console.log(this.form)时,submitForm功能正常。

任何解决方案的人?

- Formik版本:最新 - React版本:v16 - 操作系统:Mac OS

9 个答案:

答案 0 :(得分:13)

您可以将formikProps.submitForm(Formik的程序化提交)绑定到父组件,然后触发父组件的提交:

import React from 'react';
import { Formik } from 'formik';

class MyForm extends React.Component {
    render() {
        const { bindSubmitForm } = this.props;
        return (
            <Formik
                initialValues={{ a: '' }}
                onSubmit={(values, { setSubmitting }) => {
                    console.log({ values });
                    setSubmitting(false);
                }}
            >
                {(formikProps) => {
                    const { values, handleChange, handleBlur, handleSubmit } = formikProps;

                    // bind the submission handler remotely
                    bindSubmitForm(formikProps.submitForm);

                    return (
                        <form noValidate onSubmit={handleSubmit}>
                            <input type="text" name="a" value={values.a} onChange={handleChange} onBlur={handleBlur} />
                        </form>
                    )
                }}
            </Formik>
        )
    }
}

class MyApp extends React.Component {

    // will hold access to formikProps.submitForm, to trigger form submission outside of the form
    submitMyForm = null;

    handleSubmitMyForm = (e) => {
        if (this.submitMyForm) {
            this.submitMyForm(e);
        }
    };
    bindSubmitForm = (submitForm) => {
        this.submitMyForm = submitForm;
    };
    render() {
        return (
            <div>
                <button onClick={this.handleSubmitMyForm}>Submit from outside</button>
                <MyForm bindSubmitForm={this.bindSubmitForm} />
            </div>
        )
    }
}

export default MyApp;

答案 1 :(得分:6)

此处描述了我找到的最佳解决方案 https://stackoverflow.com/a/53573760

在此处复制答案:

向表单添加“id”属性:id='my-form'

class CustomForm extends Component {
    render() {
        return (
             <form id='my-form' onSubmit={alert('Form submitted!')}>
                // Form Inputs go here    
             </form>
        );
    }
}

然后在表单外的目标按钮的“form”属性中添加相同的Id:

<button form='my-form' type="submit">Outside Button</button>

现在,“外部按钮”按钮将完全等效,就好像它在表单内部一样。

注意:IE11 不支持此功能。

答案 2 :(得分:4)

对于任何想知道通过React钩子解决方案是什么的人

// Attach this to your <Formik>
const formRef = useRef()

const handleSubmit = () => {
  if (formRef.current) {
    formRef.current.handleSubmit()
  }
}

答案 3 :(得分:4)

您不需要使用ref,自定义钩子useFormikContext提供了一种在树下任意位置使用Submit的方法,其中一种条件是根组件必须是formik组件:

   const { values, submitForm } = useFormikContext();

答案 4 :(得分:2)

我刚刚遇到了同样的问题,并找到了一个非常简单的解决方案,希望对您有所帮助:

这个问题可以用普通的 html 解决。如果您在 id 上放置 form 标签,那么您可以使用按钮的 form 标签通过按钮定位它。

示例:

      <button type="submit" form="form1">
        Save
      </button>
      <form onSubmit={handleSubmit} id="form1">
           ....
      </form>

您可以将表单和按钮放在任何地方,甚至可以分开放置。

此按钮然后将触发表单提交功能,formik 将像往常一样捕获该过程。 (只要在呈现按钮时将表单呈现在屏幕上,那么无论表单和按钮位于何处,这都将起作用)

答案 5 :(得分:1)

如果您使用 withFormik,这对我有用:

  const handleSubmitThroughRef = () => {
    newFormRef.current.dispatchEvent(
      new Event("submit", { cancelable: true, bubbles: true })
    );
  };

只需在您的表单上放置一个常规的 react ref:

  <form
        ref={newFormRef}
        
        onSubmit={handleSubmit}
      >

答案 6 :(得分:0)

找到了罪魁祸首。

Formik道具上不再有onSubmitCallback。应将其更改为onSubmit

答案 7 :(得分:0)

我建立了一个基于钩子的示例。

https://codesandbox.io/s/formik-submit-button-outside-form-d825u

答案 8 :(得分:0)

你可以试试

const submitForm = ({ values, setSubmitting }) =>{//...在这里做点什么}

submitForm({values, setSubmitting})> {()=>(//...在这里做点什么)}