Skip to content

feat: Expose toDataURL and toBlob Canvas APIs via onUpdate prop#406

Open
ObaidBuilds wants to merge 1 commit into
zpao:trunkfrom
ObaidBuilds:feat/expose-canvas-api
Open

feat: Expose toDataURL and toBlob Canvas APIs via onUpdate prop#406
ObaidBuilds wants to merge 1 commit into
zpao:trunkfrom
ObaidBuilds:feat/expose-canvas-api

Conversation

@ObaidBuilds

@ObaidBuilds ObaidBuilds commented May 25, 2026

Copy link
Copy Markdown

Description

Adds an optional onUpdate callback prop to the <QRCodeCanvas> component to expose standard canvas toDataURL and toBlob export methods. This enables consumers to easily download or process the generated QR code image without complicating the component's main API parameters. To prevent parent component rendering loops, the exposed API object reference remains stable across renders.

Changes

  • Props & Types: Added optional onUpdate callback to QRCodeCanvas and exported its typescript type definition QRCodeCanvasUpdateAPIs.
  • Performance / Stability: Wrapped the exposed methods in a stable useMemo reference to prevent parent component re-render loops.
  • Integration: Invoked the callback at the end of the drawing useEffect hook.
  • Unit Tests: Added tests verifying callback invocation, API functionality, and reference stability across component updates (re-renders).

How to use

You can pass the onUpdate callback to <QRCodeCanvas> and use the received APIs to download the QR code image:

import React, { useState } from 'react';
import { QRCodeCanvas, QRCodeCanvasUpdateAPIs } from 'qrcode.react';

function DownloadableQRCode() {
  const [canvasApis, setCanvasApis] = useState<QRCodeCanvasUpdateAPIs | null>(null);

  const handleDownload = () => {
    if (!canvasApis) return;
    
    const dataUrl = canvasApis.toDataURL('image/png');
    const a = document.createElement('a');
    a.href = dataUrl;
    a.download = 'qrcode.png';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  };

  return (
    <div>
      <QRCodeCanvas 
        value="https://react.dev" 
        onUpdate={setCanvasApis} 
      />
      <button onClick={handleDownload} disabled={!canvasApis}>
        Download
      </button>
    </div>
  );
}

@zpao

zpao commented Jun 23, 2026

Copy link
Copy Markdown
Owner

I'm not against the premise here but I am curious about what makes this mechanism better than something more simple. The underlying canvas node is available directly via the ref. Now, that doesn't give you the same onUpdate callback approach so I could see an argument for something along those lines. But goal is really to keep the API surface minimal and as consistent as possible between canvas & svg - ref to access the native nodes gives me that.

BUT I don't use this component to its fullest so I'm up for understanding better.

Edit: see also #388 where this has come up previously

@zpao zpao added the canvas Issues with the Canvas component label Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

canvas Issues with the Canvas component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants