我想重复使用组件中的 formik 表单。为了做到这一点,我需要监听表单值的变化,以便调用两个函数,
getFormValues
和getFormErrors
,这两个函数将由父组件传递:
import React from "react";
import * as Yup from 'yup';
import { Formik } from 'formik';
import CheckBox from "@react-native-community/checkbox";
import { Text, TextInput } from "react-native";
import { errorStyle } from "../../styles/form.styles";
export default function UserCredentialForm({getFormValues, getFormErrors}) {
const formSchema = Yup.object().shape({
email: Yup.string().email()
.required('Required'),
password: Yup.string()
.test('lenght', 'min 5chr max 10chr', (val = '') => val.length > 4 && val.length < 11)
.required('Required'),
});
const [state, setState] = React.useState({
form: {
email: '',
password: '',
}
});
const formRef = React.useRef({} as any);
React.useEffect(() => {
console.log('formref', formRef.current.values);
getFormValues(formRef.current.values);
getFormErrors(formRef.current.errors);
}, [formRef.current.values, formRef.current.errors]);
return (
<Formik innerRef={formRef} validationSchema={formSchema} initialValues={state.form} onSubmit={() => {}}>
{({ handleChange, values, touched, errors }) => (
<React.Fragment>
{errors.password && touched.password ? <Text>{errors.email}</Text> : null}
<TextInput
style={errors.email && touched.email ? errorStyle.input : null}
keyboardType='email-address'
onChangeText={handleChange('email')}
value={values.email}
placeholder="email"
/>
{errors.password && touched.password ? <Text>{errors.password}</Text> : null}
<TextInput
style={errors.password && touched.password ? errorStyle.input : null}
onChangeText={handleChange('password')}
value={values.password}
placeholder="password"
secureTextEntry={true}
/>
</React.Fragment>
)}
</Formik>
);
}
如您所见,我正在使用链接到表单引用值的
useEffect
钩子,但它仅在表单首次渲染时被调用一次。我缺少什么?
我如何订阅所有值更改?
在这里找到解决方案:
https://stackoverflow.com/a/56269090/752636
我需要将钩子移到表格内
<Formik
initialValues={initialValues}
...
>
{props => {
getFormErrors(props.errors); // store values in state 'formValues'
getFormValues(props.values); // or use any function to get values like this
return (
<form onSubmit={props.handleSubmit}>
使用
useFormikContext
钩子来获取值。您不应该在 useEffect 中使用 ref 因为改变 ref.current
不会触发渲染。
这是useFormikContext
钩子的实现
这对我有用: 您尝试在 Formik 组件内部声明 formik 上下文,如文档中所述:
因此,只有存在可以从中提取数据的父 Formik React Context 时,此挂钩才会起作用。
然后,当其他特定值发生变化时,您只需通过实现 useEffect 直接更新值,这是我的代码:
<Formik
initialValues={inits}
enableReinitialize={true}
validationSchema={validationSchema}
onSubmit={handleFormSubmit}
>
{(props) => {
const {values, setFieldValue} = useFormikContext<Iinits>();
useEffect(() => {
if (values?.A && values?.B) {
setFieldValue('total', values.A + values.B)
}
}, [values?.A, values?.B, setFieldValue])
return (
<Form>
<div className='d-flex flex-column'>
...
</div>
</Form>
)
}}
</Formik>