一般性建议与apollo钩子和太多的重新演绎。

问题描述 投票:1回答:1

背景。我试图实现一个文件上传与DropZone到s3和graphql服务presigned url的put和get,虽然它可能不是完美的,它确实工作。我现在遇到的问题是,当我添加useMutation将结果推送到graphlql端,写到mongodb数据库时,我得到了太多的重新渲染,所以寻求建议,如何真正理解这里发生的事情。由于我的代码可能是丑陋的上传到s3工作,一旦我没有addFileS3(文件)的addFileS3(文件)是调用useMutation到grpahql写的结果到mongoDB,所以我可以检索文件在以后的点,所以我假设最好的地方是响应从axios。

const DropZone = ({ folderId, folderProps }) => {
  const [createS3File] = useMutation(ADD_FILE_S3);
  const addFileS3 = (file) => {
    createS3File({
      variables: {
        folderId: folderId,
        fileName: file.name,
      },
    })
      .then(({ data }) => {
        console.log("data", data);
      })
      .catch((e) => {
        console.log(e);
      });
  };
  const {
    acceptedFiles,
    getRootProps,
    getInputProps,
    isDragActive,
    isDragAccept,
    isDragReject,
  } = useDropzone({ accept: "image/*, application/pdf" });
  const [
    getPutURL,
    { loading: loading_url, error: error_url, data: data_url },
  ] = useLazyQuery(GET_S3_PUT_URL);
  if (loading_url) {
    console.log("loading");
  } else if (error_url) {
    console.log(error_url);
  } else if (data_url) {
    const results = data_url.PUTURL;
    results.map((file) => {
      const fileResult = acceptedFiles.filter(function(fileAcc) {
        return fileAcc.name === file.name;
      });

      const options = {
        params: {
          Key: file.name,
          ContentType: file.type,
        },
        headers: {
          "Content-Type": file.type,
        },
      };
      axios
        .put(file.url, fileResult[0], options)
        .then((res) => {
          //once i add the below here or outside axios post it goes mental on uploads
          addFileS3(file);
        })
        .catch((err) => {
        });
    });
  }

  const acceptedFilesItems = acceptedFiles.map((file) => {
    return (
      <li key={file.path}>
        {file.path} - {file.size} bytes
      </li>
    );
  });

  const uploadDocs = () => {
    let files = [];
    acceptedFiles.map((file) => {
      const fileObj = { name: file.name, type: file.type };
      files.push(fileObj);
    });

    return getS3URLResult(files);
  };

  const getS3URLResult = async (files) => {
    getPutURL({
      variables: {
        packet: files,
      },
    });
  };



  return (
    <StyledDropZone>
      <div className="container">
        <Container
          {...getRootProps({ isDragActive, isDragAccept, isDragReject })}
        >
          <input {...getInputProps()} />
          <p>Drag 'n' drop some files here, or click to select files</p>
        </Container>
        {acceptedFilesItems}
      </div>
      <button onClick={() => uploadDocs(acceptedFiles)}>Upload</button>
    </StyledDropZone>
  );
};
reactjs graphql react-apollo
1个回答
0
投票

你在渲染 "流 "期间提出axios请求,而不是在事件处理链中。它被调用,改变状态,并导致下一次重新渲染--无限循环。

突变和懒惰查询都有可能使用 onCompleted 处理程序。这是一个连锁调用下一个动作的地方(使用 data 结果参数)。)

......另外,hanlder不应该返回任何东西(return getS3URLResult(files);)--就叫它(getS3URLResult(files);)或直接 getPutURL.

更新

可能你要找的是这样的东西。

const DropZone = ({ folderId, folderProps }) => {
  const {
    acceptedFiles,
    getRootProps,
    getInputProps,
    isDragActive,
    isDragAccept,
    isDragReject,
  } = useDropzone({ accept: "image/*, application/pdf" });

  const uploadDocs = () => {
    let files = [];
    acceptedFiles.map((file) => {
      const fileObj = { name: file.name, type: file.type };
      files.push(fileObj);
    });
    console.log("uploadDocs, from acceptedFiles", files);
    // return getS3URLResult(files);
    getPutURL({
      variables: {
        packet: files,
      },
    });

  };

  const [
    getPutURL,
    { loading: loading_url, error: error_url, data: data_url },
  ] = useLazyQuery(GET_S3_PUT_URL, {
    onCompleted: (data) => {
      console.log("PUT_URL", data);

      const results = data.PUTURL;
      results.map((file) => {
        const fileResult = acceptedFiles.filter(function(fileAcc) {
          return fileAcc.name === file.name;
        });
        const options = {
          params: {
            Key: file.name,
            ContentType: file.type,
          },
          headers: {
            "Content-Type": file.type,
          },
        };
        axios
          .put(file.url, fileResult[0], options)
          .then((res) => {
            console.log("axios PUT", file.url);
            // addFileS3(file);
            createS3File({
              variables: {
                folderId: folderId,
                fileName: file.name,
              },
            })
          })
          .catch((err) => {
          });
      });

    }
  });

  const [createS3File] = useMutation(ADD_FILE_S3,{
    onCompleted: (data) => {
      console.log("ADD_FILE_S3", data);
      //setUploadedFiles( uploadedFiles,concat(data.somefilename) );
    }
  });                         

  const [uploadedFiles, setUploadedFiles] = useState( [] );


  const acceptedFilesItems = acceptedFiles.map((file) => {
    return (
      <li key={file.path}>
        {file.path} - {file.size} bytes
      </li>
    );
  });   

  const renderUploadedFiles ...

  return (
    <StyledDropZone>
      <div className="container">
        <Container
          {...getRootProps({ isDragActive, isDragAccept, isDragReject })}
        >
          <input {...getInputProps()} />
          <p>Drag 'n' drop some files here, or click to select files</p>
        </Container>
        {acceptedFilesItems}
        {uploadedFiles.length && <div class="success">
          {renderUploadedFiles}
        </div>}
      </div>
      <button onClick={() => uploadDocs(acceptedFiles)}>Upload</button>
    </StyledDropZone>
  );
};

一些优化应该被添加(useCallback),而不是为了清晰而放置。

为了更多的可读性和优化(限制reerenderings)......。我会把几乎所有的(处理)都移到单独的子组件中--通过 acceptedFiles 作为道具,在里面渲染上传按钮。

© www.soinside.com 2019 - 2024. All rights reserved.