首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更新react query onSuccess事件中的react状态会导致内存泄漏。

更新react query onSuccess事件中的react状态会导致内存泄漏。
EN

Stack Overflow用户
提问于 2022-02-27 08:24:38
回答 1查看 1.6K关注 0票数 0

我有一个叫做ImageDisplay的组件。该组件使用自定义的react钩子(useImageUpload)使用react将图像上传到cloudinary。

自定义钩子useImageUpload包含一个状态,它将上传图像的urls存储在数组中。自定义钩子返回一个对象,该对象包含图像urls数组、用于上载新图像的函数和isLoading布尔值。

正在成功上传图像。但是看起来,这个响应查询片段正在导致内存泄漏。

代码语言:javascript
复制
  onSuccess: ({ data }) => {
    console.log("Image uploaded successfully");
    setImages([...images, data.secure_url]);
  },

如何更新onSuccess事件上的图像数组?

ImageDisplay.js

代码语言:javascript
复制
import React, { useEffect } from "react";
import "styles/ImageDisplay.scss";
import { Field } from "formik";
import Skeleton from "react-loading-skeleton";
import "react-loading-skeleton/dist/skeleton.css";
import useImageUpload from "utils/useImageUpload";

export default function ImageDisplay() {
  let { images, uploadImage, uploading } = useImageUpload();

  const handleFileChange = (e) => {
    const inputFile = e.target.files[0];
    uploadImage(inputFile);
  };
  useEffect(() => {
    console.log(images);
  }, [images]);

  return (
    <>
      <div className="image-display border mb-3 px-3">
        <div className="image-preview text-center">
          <h6>Upload product images to attract customers</h6>
          {/* <Skeleton width={300} height={300} /> */}
        </div>
        <hr />
        <div className="img-choose border p-2 ">
          <div className="options">
            <Skeleton width={100} height={100} />
            <Skeleton width={100} height={100} />
            <Skeleton width={100} height={100} />
            <Skeleton width={100} height={100} />
            <Skeleton width={100} height={100} />
            <Skeleton width={100} height={100} />
          </div>
        </div>
        .
      </div>
      <div className="img-input">
        <Field
          type="file"
          name="productImages"
          id="productImages"
          onChange={handleFileChange}
          accept="image/*"
        />
        <h5>Select product images to upload</h5>
      </div>
    </>
  );
}

useImageUpload.js

代码语言:javascript
复制
import axios from "axios";
import { useState } from "react";
import { useMutation } from "react-query";

const useImageUpload = () => {
  const [images, setImages] = useState([]);

  let { isLoading: uploading, mutateAsync: uploadImage } = useMutation(
    async (data) => {
      let formData = new FormData();
      formData.append("file", data);
      formData.append("upload_preset", "uploadPresetHere");
      formData.append("cloud_name", "nameHere");

      return await axios.post(
        "cloudinary_url",
        formData,
        {
          withCredentials: false,
        }
      );
    },
    {
      onSuccess: ({ data }) => {
        console.log("Image uploaded successfully");
        setImages([...images, data.secure_url]);
      },
      onError: (error) => {
        console.log(error.response);
      },
    }
  );

  return { images, uploadImage, uploading };
};

export default useImageUpload;

如果我在这个问题上犯了什么错误,很抱歉。

EN

回答 1

Stack Overflow用户

发布于 2022-02-27 10:25:33

这是React查询的一种正常行为:如果使用useMutation卸载执行突变的组件卸载,则仍会调用onSuccess回调。

要修复它,您可以有几个选项:在ref中跟踪组件的挂载/卸载状态:

代码语言:javascript
复制
  const mounted = useRef(true)

  useEffect(() => {
    mounted.current = true
    () => mounted.current = false
  })

  let { ... } = useMutation(
    async (data) => {...},
    {
      onSuccess: ({ data }) => {
        if (mounted.current) {
           setImages([...images, data.secure_url]);
        }
      }
    }
  );

但不确定它在所有情况下都能工作,通常在卸载组件时响应删除引用。

另一种解决方案是将图像存储在React查询缓存中。毕竟,它是来自服务器的数据,因此它处于服务器状态,应该驻留在缓存中:

代码语言:javascript
复制
  let { ... } = useMutation(
    async (data) => {...},
    {
      onSuccess: ({ data }) => {
         queryClient.setQueryData('images', prev => [...prev, data])
      }
    }
  );
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71283217

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档