Как Formik setFieldValue в хуке useEffect - PullRequest
0 голосов
/ 23 февраля 2020

У меня есть форма Formik, которая должна динамически изменяться на основе информации, передаваемой через маршрутизатор. Мне нужно выполнить запрос graphQL, чтобы получить некоторые данные и заполнить форму этими полученными данными. Я могу настроить форму и получить данные, но не могу понять, как установить setFieldValue для базовой формы, находясь в ловушке 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>
  );
}

1 Ответ

4 голосов
/ 24 февраля 2020

Я думаю, что понял это, но не уверен. Я нашел несколько мест, которые ссылались на опору FormR innerRef, поэтому попробовал это, и это, кажется, работает. Нигде не упоминается, что я мог увидеть в do c или в учебном пособии, поэтому я не уверен, что это какая-то функция, которая не поддерживается, или, возможно, просто предполагается, что она используется для внутренних вещей Formik, но, похоже, она работает для меня, так что я собираюсь использовать это, пока не найду лучший путь. Я уже потратил гораздо больше времени на это, чем хочу поделиться. : |

Комментарии или предложения приветствуются. Или, может быть, вы проголосуете, если считаете, что это правильный подход.

Чтобы решить эту проблему, я добавляю useRef в основное тело функции:

  const formikRef = useRef();

Затем я добавил это как проп:

      <Formik
        innerRef={formikRef}
        initialValues={initialValues}
        validationSchema={validSchema}
        onSubmit={onSubmit}
      >

Как только я это сделал, я смог ссылаться на функции Formik изнутри useEffect, поэтому в моем случае я сделал следующее:

      if (formikRef.current) {
        formikRef.current.setFieldValue(
          "platformName",
          dataGet.Platform.platformName
        );
        formikRef.current.setFieldValue(
          "platformCategory",
          dataGet.Platform.platformCategory
        );
      }
...