<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>
);
}}
/>
Run Code Online (Sandbox Code Playgroud)
我正在尝试此解决方案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
Eri*_*tin 70
仅适用于想知道通过 React hooks 解决什么问题的人:
Formik 2.x,如本答案所述
// import this in the related component
import { useFormikContext } from 'formik';
// Then inside the component body
const { submitForm } = useFormikContext();
const handleSubmit = () => {
submitForm();
}
Run Code Online (Sandbox Code Playgroud)
请记住,该解决方案仅适用于Formik 组件内的组件,因为它使用上下文 API。如果由于某种原因您想从外部组件手动提交,或者从实际使用 Formik 的组件手动提交,您实际上仍然可以使用innerRefprop。
TLDR ; 如果您提交的组件是 a<Formik>或withFormik()组件的子组件,则此上下文答案就像一个魅力,否则,请使用innerRef下面的答案。
Formik 1.5.x+
// Attach this to your <Formik>
const formRef = useRef()
const handleSubmit = () => {
if (formRef.current) {
formRef.current.handleSubmit()
}
}
// Render
<Formik innerRef={formRef} />
Run Code Online (Sandbox Code Playgroud)
Eli*_*ant 24
您可以将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;
Run Code Online (Sandbox Code Playgroud)
小智 8
我找到的最佳解决方案在这里描述/sf/answers/3750163231/
在此处复制答案:
将“id”属性添加到您的表单中:id='my-form'
class CustomForm extends Component {
render() {
return (
<form id='my-form' onSubmit={alert('Form submitted!')}>
// Form Inputs go here
</form>
);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在表单外的目标按钮的“form”属性中添加相同的Id:
<button form='my-form' type="submit">Outside Button</button>
Run Code Online (Sandbox Code Playgroud)
现在,“外部按钮”按钮将完全等效,就好像它在表单内部一样。
注意:IE11 不支持此功能。
小智 6
我刚刚遇到了同样的问题,并找到了一个非常简单的解决方案,希望这会有所帮助:
这个问题可以用 plain 解决html。如果你id在你的标签上放了一个标签,form那么你可以使用按钮的form标签用你的按钮来定位它。
例子:
<button type="submit" form="form1">
Save
</button>
<form onSubmit={handleSubmit} id="form1">
....
</form>
Run Code Online (Sandbox Code Playgroud)
您可以将表单和按钮放在任何地方,甚至可以分开。
然后,此按钮将触发表单提交功能,formik 将像往常一样捕获该过程。(只要在呈现按钮时将表单呈现在屏幕上,那么无论表单和按钮位于何处,这都将起作用)
如果将类组件转换为功能组件,自定义挂钩useFormikContext提供了一种在树下任意位置使用提交的方法:
const { values, submitForm } = useFormikContext();
Run Code Online (Sandbox Code Playgroud)
PS:这仅适用于那些并不真正需要在Formik组件外部调用submit的人,因此您可以将组件放在组件树中的更高级别,而不是使用ref Formik,并使用自定义钩子useFormikContext,但如果确实需要从外部提交,Formik您必须使用useRef .
const { values, submitForm } = useFormikContext();
Run Code Online (Sandbox Code Playgroud)
https://formik.org/docs/api/useFormikContext
2021 年,使用 16.13.1,这种方式满足了我的几个要求:
\n<Formik>元素内。请注意,如果您可以做到这一点,那么您应该使用答案useFormikContext,因为它比我的简单。(我的将允许您更改正在提交的表单(我有一个应用程序栏,但用户可以导航到多个表单)。dirty状态。)这就是我的想法:我创建了一个新的上下文提供程序,专门用于保存一些有用的 Formik 内容,以链接我的两个外部组件,这些组件位于应用程序的不同嵌套分支中(全局应用程序栏和其他地方的表单,更深层次)事实上,在页面视图 \xe2\x80\x93 中,我需要提交/重置按钮来适应用户导航到的不同表单,而不仅仅是一个;不仅仅是一个<Formik>元素,而是一次只有一个)。
以下示例使用 TypeScript,但如果您只知道 javascript,请忽略冒号后面的内容,这在 JS 中是相同的。
\n您将<FormContextProvider>应用程序放置在足够高的位置,以使其包含需要访问 Formik 内容的两个不同组件。简化示例:
<FormContextProvider>\n <MyAppBar />\n <MyPageWithAForm />\n</FormContextProvider>\nRun Code Online (Sandbox Code Playgroud)\n这是 FormContextProvider:
\n<FormContextProvider>\n <MyAppBar />\n <MyPageWithAForm />\n</FormContextProvider>\nRun Code Online (Sandbox Code Playgroud)\n在呈现元素的组件中<Formik>,我添加了这一行:
import React, { MutableRefObject, useRef, useState } from \'react\'\nimport { FormikProps, FormikValues } from \'formik\'\n\nexport interface ContextProps {\n formikFormRef: MutableRefObject<FormikProps<FormikValues>>\n forceUpdate: () => void\n}\n\n/**\n * Used to connect up buttons in the AppBar to a Formik form elsewhere in the app\n */\nexport const FormContext = React.createContext<Partial<ContextProps>>({})\n\n// https://github.com/deeppatel234/react-context-devtool\nFormContext.displayName = \'FormContext\'\n\ninterface ProviderProps {}\n\nexport const FormContextProvider: React.FC<ProviderProps> = ({ children }) => {\n // Note, can\'t add specific TS form values to useRef here because the form will change from page to page.\n const formikFormRef = useRef<FormikProps<FormikValues>>(null)\n const [refresher, setRefresher] = useState<number>(0)\n\n const store: ContextProps = {\n formikFormRef,\n // workaround to allow components to observe the ref changes like formikFormRef.current.dirty\n forceUpdate: () => setRefresher(refresher + 1),\n }\n\n return <FormContext.Provider value={store}>{children}</FormContext.Provider>\n}\nRun Code Online (Sandbox Code Playgroud)\n在同一组件中,我将此属性添加到<Formik>元素中:
const { formikFormRef } = useContext(FormContext)\nRun Code Online (Sandbox Code Playgroud)\n在同一个组件中,<Formik>元素下嵌套的第一个东西就是 this(重要的是,注意添加了这一<FormContextRefreshConduit />行)。
<Formik\n innerRef={formikFormRef}\n initialValues={initialValues}\n ...\n>\n {({ submitForm, isSubmitting, initialValues, values, setErrors, errors, resetForm, dirty }) => (\n <Form>\n <FormContextRefreshConduit />\n ...\nRun Code Online (Sandbox Code Playgroud)\n在包含提交/重置按钮的组件中,我有以下内容。注意使用formikFormRef
export const MyAppBar: React.FC<Props> = ({}) => {\n const { formikFormRef } = useContext(FormContext)\n \n const dirty = formikFormRef.current?.dirty\n\n return (\n <>\n <AppButton\n onClick={formikFormRef.current?.resetForm}\n disabled={!dirty}\n >\n Revert\n </AppButton>\n <AppButton\n onClick={formikFormRef.current?.submitForm}\n disabled={!dirty}\n >\n Save\n </AppButton>\n </>\n )\n}\nRun Code Online (Sandbox Code Playgroud)\n对于调用 Formik 方法很有ref用,但通常无法观察其dirty属性(react 不会触发此更改的重新渲染)。FormContextRefreshConduit一起forceUpdate是一个可行的解决方法。
谢谢,我从其他答案中获得了灵感,找到了一种满足我自己所有要求的方法。
\n| 归档时间: |
|
| 查看次数: |
13142 次 |
| 最近记录: |