如何在 useEffect 钩子中形成 setFieldValue

Ben*_*iga 10 reactjs react-apollo formik use-effect

我有一个 Formik 表单,需要根据通过路由器传递的信息动态更改。我需要运行一个 graphQL 查询来检索一些数据并用检索到的数据填充表单。我能够设置表单并检索数据,但我无法弄清楚如何在 useEffect 挂钩中为基础表单设置字段值。我觉得我错过了一些重要的部分来访问 Formik 上下文,但我无法从文档中找到它。

任何帮助都会很棒。

import React, { useState, useEffect } from "react";
import Router, { useRouter } from "next/router";

import Container from "react-bootstrap/Container";
import { Field, Form, FormikProps, Formik } from "formik";
import * as Yup from "yup";

import { useLazyQuery } from "@apollo/react-hooks";
import { GET_PLATFORM } from "../graphql/platforms";

export default function platformsForm(props) {
  const router = useRouter();

  // grab the action requested by caller and the item to be updated (if applicable)
  const [formAction, setFormAction] = useState(router.query.action);
  const [formUpdateId, setFormUpdateId] = useState(router.query.id);

  const [initialValues, setInitialValues] = useState({
    platformName: "",
    platformCategory: ""
  });

  const validSchema = Yup.object({
    platformName: Yup.string().required("Name is required"),
    platformCategory: Yup.string().required("Category is required")
  });

  const [
    getPlatformQuery,
    { loading, error, data: dataGet, refetch, called }
  ] = useLazyQuery(GET_PLATFORM, {
    variables: { id: formUpdateId }
  });

  useEffect(() => {
    !called && getPlatformQuery({ variables: { id: formUpdateId } });
    if (dataGet && dataGet.Platform.platformName) {
      console.log(
        dataGet.Platform.platformName,
        dataGet.Platform.platformCategory
      );

      //
      // vvv How do I set Field values at this point if I don't have Formik context
      // setFieldValue();
      //
    }
  }),
    [];

  const onSubmit = async (values, { setSubmitting, resetForm }) => {
    console.log("submitted");
    resetForm();
    setSubmitting(false);
  };

  return (
    <Container>
      <Formik
        initialValues={initialValues}
        validationSchema={validSchema}
        onSubmit={onSubmit}
      >
        {({
          handleSubmit,
          handleChange,
          handleBlur,
          handleReset,
          values,
          touched,
          isInvalid,
          isSubmitting,
          isValidating,
          submitCount,
          errors
        }) => (
          <Form>
            <label htmlFor="platformName">Name</label>
            <Field name="platformName" type="text" />

            <label htmlFor="platformCategory">Category</label>
            <Field name="platformCategory" type="text" />

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

Run Code Online (Sandbox Code Playgroud)

Ben*_*iga 20

我想我想通了,但不确定。我找到了一些提到 Formik innerRef 道具的地方,所以尝试了一下,它似乎有效。在我在文档或教程中可以看到的任何地方都没有提到它,所以我不确定这是否是一些不受支持的功能,或者可能只是应该用于内部 Formik 的东西,但它似乎对我有用所以在找到更好的方法之前,我将使用它。我已经花了更长的时间在这上面我愿意分享。:|

欢迎提出意见或建议。或者,如果您认为这是正确的方法,则可以点赞。

为了解决这个问题,我在函数主体中添加了一个 useRef:

  const formikRef = useRef();
Run Code Online (Sandbox Code Playgroud)

然后我将其添加为道具:

      <Formik
        innerRef={formikRef}
        initialValues={initialValues}
        validationSchema={validSchema}
        onSubmit={onSubmit}
      >
Run Code Online (Sandbox Code Playgroud)

一旦我这样做了,我就可以从 useEffect 中引用 Formik 函数,因此在我的情况下,我执行了以下操作:

      if (formikRef.current) {
        formikRef.current.setFieldValue(
          "platformName",
          dataGet.Platform.platformName
        );
        formikRef.current.setFieldValue(
          "platformCategory",
          dataGet.Platform.platformCategory
        );
      }
Run Code Online (Sandbox Code Playgroud)

  • 要回答上述 ts 问题,您可以执行以下操作 `import { FormikProps, FormikValues } from 'formik'` 然后 `const formikRef = useRef&lt;FormikProps&lt;FormikValues&gt;&gt;(null)` (3认同)

Ahm*_*mad 5

访问 Formik 状态和助手的正确方法是使用 Formik 的useFormikContext钩子。这为您提供了您需要的一切。

检查文档以获取详细信息和示例: https: //formik.org/docs/api/useFormikContext