【问题标题】:first download image button click is downloading .html file in react.js - next.js首先下载图片按钮点击是在 react.js - next.js 中下载 .html 文件
【发布时间】:2023-02-12 06:26:34
【问题描述】:

这是我复制的组件:

import Image from "next/image";
import { useState } from "react";
export default function Home() {
  const [downloadURL, setDownloadURL] = useState("");

  const download = async () => {
    const result = await fetch("http://localhost:3000/test.jpg", {
      method: "GET",
      headers: {},
    });
    const blob = await result.blob();
    const url = URL.createObjectURL(blob);
    setDownloadURL(url);
  };

  const handleDownload = async (e) => {
    try {
      await download();
      URL.revokeObjectURL(downloadURL);
    } catch (error) {
      console.error(error);
    }
  };
  return (
    <div className=" bg-gray-500 bg-opacity-75 transition-opacity flex flex-col justify-center  items-center">
      <Image src="/test.jpg" width={500} height={600} className="mb-2 " />
      <button
        onClick={handleDownload}
        type="button"
        className="flex-1 content-center text-center bg-indigo-600 py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
      >
        <a href={downloadURL} download={"test"}>
          Download Image
        </a>
      </button>
    </div>
  );
}

在第一次点击时,我下载了.html 文件,在接下来的点击中,我下载了图像。但我无法弄清楚是什么导致第一次点击下载 html 文件。

reproducible github repo

【问题讨论】:

  • 事件冒泡,<a download> 在 <button> 内部,所以当您单击时 - 默认 <a download> 处理程序被执行,由于初始状态为空 downloadURL,然后事件传播到按钮 - 现在按钮 onClick 是执行,设置 downloadURL 等,但实际的下载事件已经发生到那个时候。
  • @SergeySosunov 解决方案是什么?

标签: javascript reactjs image next.js blob


【解决方案1】:

这种方法的错误很少:

  1. 事件冒泡,click事件在&lt;button&gt;之前由&lt;a&gt;处理。
  2. 在 1 次点击事件期间更改了对状态变量的依赖,您正在尝试更改绑定到状态的 &lt;a&gt; href,但状态不会立即更新,它只会在下一次渲染时更新,但点击事件会不要等那个。

    我的建议:完全删除并使用旧的经典 download 函数,该函数动态创建 &lt;a&gt; 并在其上执行“单击”:

    function Home() {
      const download = (filename, content) => {
        var element = document.createElement("a");
        element.setAttribute("href", content);
        element.setAttribute("download", filename);
        element.style.display = "none";
        document.body.appendChild(element);
    
        element.click();
    
        document.body.removeChild(element);
      };
    
      const handleDownload = async (e) => {
        try {
          const result = await fetch("assets/test.png", {
            method: "GET",
            headers: {}
          });
          const blob = await result.blob();
          const url = URL.createObjectURL(blob);
          download("test", url);
          URL.revokeObjectURL(url);
        } catch (error) {
          console.error(error);
        }
      };
      return (
        <div>
          <img src="/assets/test.png" width={100} height={100} />
          <button onClick={handleDownload} type="button">
            Download Image
          </button>
        </div>
      );
    }
    

    抱歉稍微简化了您的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-21
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 2019-07-27
    • 2015-12-19
    相关资源
    最近更新 更多