聆听Formik价值观的变化

问题描述 投票:0回答:3

我想重复使用组件中的 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
钩子,但它仅在表单首次渲染时被调用一次。我缺少什么? 我如何订阅所有值更改?

reactjs react-hooks formik
3个回答
5
投票

在这里找到解决方案:

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}>

2
投票

使用

useFormikContext
钩子来获取值。您不应该在 useEffect 中使用 ref 因为改变
ref.current
不会触发渲染。 这是
useFormikContext
钩子

的实现

https://formik.org/docs/api/useFormikContext


0
投票

这对我有用: 您尝试在 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>
© www.soinside.com 2019 - 2024. All rights reserved.