So, I've basically tried everything with this one. I ran out of solutions or options. Thing is, I have a button. When you click on it your camera will open and you will see some filters that you can apply to your face. I am new to React. Made it work without the iframe to test the API first, but it's not working anymore inside this iframe. The react component needs to be inside this iframe. The code can be found here with what I did so far/tried: https://codesandbox.io/s/cool-fog-3k5si5?file=/src/components/button/button.jsx
The problem is that when I click the button, the canvas disappears from the page and I get this error in the console:
The DeepAR API fails initialization because the canvas is no longer on the page and it crashes. I really don't know what to search for as I considered this to be a react render error and I tried different ways to write the react code (functional/class). If you have any ideas or suggestions, please help. Thank you in advance.
Your use of useEffect
in your Modal
and App
Component is incorrect.
To remind you, useEffect
accepts a function which runs after the render is committed to the screen.
If the function returns a function (which is your case), this function is the "clean up" function which is run before the component is removed from the UI.
So what is happening is that your useEffect code is run only when your components are being unmounted.
Since we are not concerned with any clean up at this stage, a quick solution for you is to move the clean up expressions to the main effect function as follows:
useEffect(() => {
fetch(
"https://cors-anywhere.herokuapp.com/https://staging1.farmec.ro/rest/V1/farmec/deeparProducts/"
)
.then((response) => response.json())
.then((productsJson) => setProducts(productsJson));
}, []);
The same goes for your Modal component :
useEffect(() => {
let initializedDeepAR = new DeepAR({
licenseKey:
"6fda241c565744899d3ea574dc08a18ce3860d219aeb6de4b2d23437d7b6dcfcd79941dffe0e57f0",
libPath: DeepAR,
deeparWasmPath: deeparWasm,
canvas: canvas.current,
segmentationConfig: {
modelPath: segmentationMode
},
callbacks: {
onInitialize: () => {
// let filterName = colors[0].filterData[0]['Filter Binary Path'].match(new RegExp("[^/]+(?=\\.[^/.]*$)"))[0];
setDeepAR(initializedDeepAR);
initializedDeepAR.startVideo(true);
// initializedDeepAR.switchEffect(0, 'slot', `https://staging1.farmec.ro/media/deepArFilters/${filterName}.bin`);
}
}
});
/*@TODO: replace paths with server local path*/
initializedDeepAR.downloadFaceTrackingModel(models);
}, []);
With one additional fix concerning your use of useRef
.
To target the element behind the useRef
, you must use the .current
property.
Finally, your Frame component is using useState
to manage the mounting of the iframe. I would suggest using the useRef
hook with a useState
for your mountNode
as follows:
export const Frame = ({
children,
styleSelector,
title,
...props
}) => {
const contentRef = useRef(null)
const [mountNode, setMountNode] = useState()
useEffect(() => {
setMountNode(contentRef.current.contentWindow.document.body)
}, [])
useEffect(() => {
const win = contentRef.current.contentWindow
const linkEls = win.parent.document.querySelectorAll(
styleSelector
)
if (linkEls.length) {
linkEls.forEach((el) => {
win.document.head.appendChild(el)
})
}
}, [styleSelector])
return (
<iframe title={title} {...props} ref={contentRef}>
{mountNode && createPortal(children, mountNode)}
</iframe>
)
}