Первое нажатие кнопки загрузки изображения загружает файл .html в react.js - next.js

Это компонент, который я воспроизвел:

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.

воспроизводимый репозиторий github

Событие всплывает, <a download> находится внутри <button>, поэтому, когда вы нажимаете — по умолчанию выполняется обработчик <a download>, с пустым URL-адресом загрузки из-за начального состояния, затем событие распространяется до кнопки — теперь кнопка onClick выполнено, установка URL-адреса загрузки и т. д., но фактическое событие загрузки уже произошло до этого времени.

Sergey Sosunov 23.01.2023 00:06

@SergeySosunov, какое решение?

Yilmaz 11.02.2023 22:26
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Несколько ошибок при таком подходе:

  1. Событие всплывает, событие click обрабатывается <a> перед <button> onClick.
  2. Зависимость от переменной состояния изменилась во время 1 события клика, вы пытаетесь изменить <a> href, который привязан к состоянию, но состояние не обновляется сразу, оно будет обновлено только при следующем рендере, но событие клика не будет ждать этого (пропуская тот факт, что это делается с помощью асинхронной операции).

Что я рекомендую: полностью удалить <a> и использовать старую классическую функцию скачать, которая создает <a> на лету и выполняет «щелчок» по нему:

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>
  );
}

Извините, что немного упростил ваш код.

Другие вопросы по теме