So, I am using react to create an image generator. With different components (header, sidebar and bannercontent). In the header I have a button which, when clicked, should generates an image that is located in the bannercontent, which holds a canvas element.
Now I know I can use ref attributes when the elements are in the same component (is easier done), but getting data from the canvas to be generated when the button in the header is clicked, only shows an error:
Cannot read properties of null (reading 'cloneNode')
We use a reducer with dispatch to move data (which is set on the sidebar) to the bannercontent, which works fine.
We use the following code:
This is inside a file called: useBanner.ts
const downloadRef = useRef(null!);
const handleDownloadImage = () => {
const targetEl = downloadRef.current;
DomToImage.toJpeg(targetEl, { quality: 0.95 }).then((dataUrl: any) => {
const link = document.createElement('a');
link.download = 'aff-banner.jpeg';
link.href = dataUrl;
link.click();
});
};
return {
downloadRef,
handleDownloadImage
}
On the bannercontent file we have:
import React from 'react';
import { useBanner } from '../../reducer/useBanner';
const BannerContent = (): React.ReactElement => {
const { downloadRef } = useBanner();
return (
<div ref={downloadRef}>
<canvas ....></canvas>
</div>
);
}
export default BannerContent;
And on the header file:
import { useBanner } from '../../reducer/useBanner';
const Header = (): ReactElement => {
const {
handleDownloadImage
} = useBanner();
return (
<Button onClick={handleDownloadImage}>Download Banner</Button>
);
};
export default Header;
Oh and the structure of those components is:
import Sidebar from '../Sidebar/Sidebar';
import BannerContent from '../BannerContent/BannerContent';
import { BannerProvider } from '../context/BannerContext';
import Header from '../Header/Header';
export default function Content() {
return (
<BannerProvider>
<Header />
<Sidebar />
<BannerContent />
</BannerProvider>
);
}