Fork me on GitHub
#reagent
<
2023-10-12
>
wevrem16:10:05

Oh boy, I’ve waded out way beyond my ability. Details coming in thread.

wevrem16:10:16

I’m trying to adapt https://github.com/zpao/qrcode.react/blob/trunk/examples/download.tsx for downloading an SVG. Here is an extract of the JS code:

function DownloadDemo() {
  const svgRef = useRef<SVGSVGElement>(null);

  function onSVGButtonClick() {
    const node = svgRef.current;
    if (node == null) {
      return;
    }
    ... grab SVG guts, serialize, trigger download ...
  }

  return (
    <>
      <div className="container">
        <div>
          <QRCodeSVG ref={svgRef} value="hello world" />
          <button onClick={onSVGButtonClick}>
            download
          </button>
        </div>
      </div>
    </>
  );
}
I look at this and say “Oh, cool, I just need to pass a ref to the QRCodeSVG component, I know how to do that.” I’ve set up refs with (let [qr-ref (atom nil)] ...) and then passed them along with something like [:div {:ref #(reset! qr-ref %)}] but that doesn’t work. It also doesn’t work if I set up my-ref with (useRef nil). Either way I get an error that function components can’t use refs and I should be using forwardRef. What I don’t understand (well, one thing among many) is QRCodeSVG is itself defined with forwardRef, so I’m not sure why I need to be using it yet again. I’ve come up with something that works in the sense that all warnings and errors are silenced, but it doesn’t work in a way that is important: (.current qr-ref) is always nil.

wevrem01:10:01

I managed to get it to work by calling the QRCodeSVG function directly. And by converting the params to js with clj->js. I’m glad that works, but it seems like something I shouldn’t need to do and instead that reagent should be doing for me. Maybe?

(defn qr-component [...]
  (let [qr-ref (react/useRef nil)
        ...]
    [:div
     (qrcode/QRCodeSVG (clj->js {:value val
                                 :ref qr-ref
                                 ...}))
     [:div.icons {:on-click (fn [_e] ... download using (.-current qr-ref) ...)}]]))

(defn main-page [...]
  ...
   [:f> qr-component ...])

mikerod04:10:35

Did you adapt-react-class on QRCodeSVG? When you tried it with :ref ?

wevrem04:10:04

I did try it (and just tried it again) but still get the same family of errors, warnings to use forwardRef.

jahson16:10:35

You could, at least, wrap QRCodeSvg in a div and use ref on this div.

jahson16:10:26

[:div {:ref (fn [x] (js/console.log "ref" x))} [:> qrcode/QRCodeCanvas {:value "value"}]]

jahson16:10:04

> You could, at least, wrap QRCodeSvg in a div and use ref on this div. Then you will be able to use standard DOM methods to get children.

jahson16:10:59

I’ve tried to use https://github.com/zpao/qrcode.react/blob/trunk/examples/download.tsx with just React, but still got the same error about forwardRef.

wevrem22:10:21

Thank you @U071CG4QY. I didn’t even think to check issues on the qrcode.react project, I just assumed I was doing something wrong. I’ll try the suggestion of putting the ref on a wrapping div. At least I have a working solution with my very non-reagent approach.