Home > Enterprise >  Button download always target and download the first svg in my collection , how to make it work so t
Button download always target and download the first svg in my collection , how to make it work so t

Time:01-30

I try to create a qrcode app with react. After the user submit form with value to create a svg , they can also download it. But i cant make it work , each time it download the same svg.

my download function

 const downloadQRCode = (e) => {
    e.preventDefault();

    let svg = qrRef.current.querySelector("svg");


    let svgXML = new XMLSerializer().serializeToString(svg);
    

    let dataUrl = "data:image/svg,"   encodeURIComponent(svgXML);

    let anchor = document.createElement("a");
    anchor.href = dataUrl;
    anchor.download = `qr-code.svg`;
    document.body.appendChild(anchor);
    anchor.click();
    document.body.removeChild(anchor);
  };

Here i use map to render qrcode component and a button to download the svg

 qrcode.map((item) => {
 return (
  <li ref={qrRef}>

         <QRCode
              className="qrcode"
              size={item.size}
              value={item.value}
              bgColor={item.bgcolor}
              fgColor={item.fgcolor}
              level="L"
              renderAs="svg">
        </QRCode>

    <form onSubmit={downloadQRCode}>
     <button type="submit">Download</button>
   </form>

  </li>
)
}

CodePudding user response:

It looks like you are using a single React ref for all the qrcode you are mapping. I suggest using an array of React refs and passing this to the button's onClick handler.

const qrcodeRefs = React.useRef([]);

qrcodeRefs.current = qrcode.map((_, i) => qrcodeRefs.current[i] ?? createRef());

...

const downloadQRCode = (qrRef) => e => {
  const svg = qrRef.current.querySelector("svg");
  const svgXML = new XMLSerializer().serializeToString(svg);
  const dataUrl = "data:image/svg,"   encodeURIComponent(svgXML);

  const anchor = document.createElement("a");
  anchor.href = dataUrl;
  anchor.download = `qr-code.svg`;
  document.body.appendChild(anchor);
  anchor.click();
  document.body.removeChild(anchor);
};

...

qrcode.map((item, index) => {
  return (
    <li ref={qrcodeRefs.current[i]}>
      <QRCode
        className="qrcode"
        size={item.size}
        value={item.value}
        bgColor={item.bgcolor}
        fgColor={item.fgcolor}
        level="L"
        renderAs="svg"
      />
      <button type="button" onClick={downloadQRCode(qrcodeRefs.current[i])}>
        Download
      </button>
    </li>
  )
}

CodePudding user response:

if you use ref in a loop, it will hold the last value. you do not need a ref, replace

let svg = qrRef.current.querySelector("svg");

with

// e.target.parentNode is the li dom
let svg = e.target.parentNode.querySelector("svg");

  •  Tags:  
  • Related