内存泄漏反应

时间:2020-01-19 19:00:09

标签: reactjs react-hooks formik

提交表单时,我得到警告以下。提交后卸载该组件。该如何解决?

警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务。

在Formik中(在ItemCodeSpecForm.js:82处) 在模态中(在ItemCodeSpecForm.js:80处) 在ErrorBoundary中(在ItemCodeSpecForm.js:77处) 在Suspense中(在ItemCodeSpecForm.js:76处) 在div中(在ItemCodeSpecForm.js:74处) 在ItemCodeSpecForm中(在EditItemCodeSpec.js:61处) 在div中(位于EditItemCodeSpec.js:60)

下面是表格

function ItemCodeSpecForm({ formType, mutation, removeSelect, initialData }) {
  const { number } = useParams();
  const itemCode = parseInt(number);
  const [open, setOpen] = useState(false);

  const client = useApolloClient();

  const gradeOptions = [
    { value: "HUMAN", label: "HUMAN" },
    { value: "DEFAULT", label: "DEFAULT" }
  ];

  const specClassOptions = [
    { value: "DS", label: "DS" },
    { value: "STAB", label: "STAB" }
  ];

  const defaultAdditional = {
    cursor: null
  };
  const shouldLoadMore = (scrollHeight, clientHeight, scrollTop) => {
    const bottomBorder = (scrollHeight - clientHeight) / 2;
    return bottomBorder < scrollTop;
  };
  const loadOptions = async (q = 0, prevOptions, { cursor }) => {
    console.log("qu", q * 1);
    const options = [];
    console.log("load");
    const response = await client.query({
      query: GET_PRODUCTS,
      variables: {
        filter: {
          number_gte: q * 1
        },
        skip: 0,
        first: 5,
        after: cursor
      }
    });

    console.log("res", response);
    response.data.products.products.map(item => {
      options.push({
        value: item.number,
        label: `${item.number} ${item.description}`
      });
    });

    return {
      options,
      hasMore: response.data.products.hasMore,
      additional: {
        cursor: response.data.products.cursor.toString()
      }
    };
  };

  const handleShow = () => {
    setOpen(true);
  };

  const handleHide = () => {
    setOpen(false);
  };

  return (
    <div className="modal">
      <button onClick={handleShow}>{formType}</button>
      <Suspense fallback={<div>Loading...</div>}>
        <ErrorBoundary>
          {open ? (
            <Modal>
              <button onClick={handleHide}>&#10006;</button>
              <Formik
                initialValues={{
                  product: !!initialData
                    ? { value: initialData.product, label: initialData.product }
                    : "",
                  spec_class: !!initialData
                    ? {
                        value: initialData.spec_class,
                        label: initialData.spec_class
                      }
                    : "",
                  grade: !!initialData
                    ? { value: initialData.grade, label: initialData.grade }
                    : ""
                }}
                validationSchema={Yup.object().shape({
                  product: Yup.string().required("Required"),
                  spec_class: Yup.string().required("Required"),
                  grade: Yup.string().required("Required")
                })}
                onSubmit={(data, { setSubmitting, resetForm }) => {
                  setSubmitting(true);
                  const { product, spec_class, grade } = data;
                  console.log({
                    variables: {
                      input: {
                        itemCode,
                        product: product.value,
                        spec_class: spec_class.value,
                        grade: grade.value
                      }
                    }
                  });
                  formType === "Add" ? console.log("a") : console.log("e");
                  formType === "Add"
                    ? mutation({
                        variables: {
                          input: {
                            itemCode,
                            product: product.value,
                            spec_class: spec_class.value,
                            grade: grade.value
                          }
                        }
                      })
                    : mutation({
                        variables: {
                          id: initialData.id,
                          input: {
                            product: product.value,
                            spec_class: spec_class.value,
                            grade: grade.value
                          }
                        }
                      });
                  setSubmitting(false);
                  resetForm();
                }}
              >
                {({
                  values,
                  isSubmitting,
                  handleChange,
                  setFieldValue,
                  touched,
                  errors
                }) => (
                  <Form>
                    <label htmlFor="product">Product</label>
                    <AsyncPaginate
                      name="product"
                      defaultOptions
                      debounceTimeout={300}
                      cacheOptions
                      additional={defaultAdditional}
                      value={values.product && values.product}
                      loadOptions={loadOptions}
                      onChange={option => setFieldValue("product", option)}
                      shouldLoadMore={shouldLoadMore}
                    />
                    {touched.product && touched.product ? (
                      <div>{errors.product}</div>
                    ) : null}
                    <label htmlFor="grade">Grade</label>
                    <Select
                      name="grade"
                      defaultValue={values.grade}
                      value={
                        gradeOptions
                          ? gradeOptions.find(
                              option => option.value === values.grade
                            )
                          : ""
                      }
                      options={gradeOptions}
                      onChange={option => setFieldValue("grade", option)}
                    />
                    {errors.grade && touched.grade ? <div>Required</div> : ""}
                    <label>Spec Class</label>
                    <Select
                      name="spec_class"
                      defaultValue={values.spec_class}
                      value={
                        specClassOptions
                          ? specClassOptions.find(
                              option => option.value === values.spec_class
                            )
                          : ""
                      }
                      options={specClassOptions}
                      onChange={option => setFieldValue("spec_class", option)}
                    />
                    {touched.spec_class && errors.spec_class ? (
                      <div>Required</div>
                    ) : (
                      ""
                    )}
                    <div>
                      <button disabled={isSubmitting} type="submit">
                        Submit
                      </button>
                    </div>
                    <pre>{JSON.stringify(values, null, 2)}</pre>
                  </Form>
                )}
              </Formik>
            </Modal>
          ) : null}
        </ErrorBoundary>
      </Suspense>
    </div>
  );
}

1 个答案:

答案 0 :(得分:0)

  useEffect(() => {

       return () => {
         //for cleanup
       };
  });

您有一个需要卸载组件时进行清理的代码。例如eventListener