resium
resium copied to clipboard
ref.current && ref.current.cesiumElement may always be undefined in docs
I've found ref.current && ref.current.cesiumElement
may always be undefined in https://resium.reearth.io/guide#way-1-useref-hooks-function-component
Looks like it could be related to https://medium.com/@teh_builder/ref-objects-inside-useeffect-hooks-eb7c15198780 ?
got the same issue
Identical problem. I also noticed that when the server is restarted, a change is made and the problem goes away, but as soon as the page is refreshed, the problem appears again.
I noticed that when executing part of the code, console.log-0 shows that everything exists, and console.log - 1 displays undifind. I can assume that there is some kind of delay in processing... Iām still deciding how to get around this feature.
console.log(0, this.ref.cesiumElement) if (this.ref.current && this.ref.current.cesiumElement) { console.log(1, this.ref.current.cesiumElement)}
So. I tried to set the delay to 1 ms and it worked. I assume that when launched synchronously, it does not have time to work out the render function or runs it several times and useEffect thinks that it can work, but in fact useRef is not yet defined. Therefore, the condition is not met and the function does not work.
Now the question. Is it possible to do something asynchronously or set a wait in useEffect for the condition to be met?
import { useEffect, useRef } from "react"; import { Viewer } from "resium";
const ExampleComponent = () => { const ref = useRef(null);
useEffect(() => { console.log(ref.current.cesiumElement) setTimeout(()=>{ if (ref.current && ref.current.cesiumElement) { console.log(ref.current.cesiumElement) // ref.current.cesiumElement is Cesium's Viewer // DO SOMETHING } },1)
}, []);
return <Viewer ref={ref} />; }; export default ExampleComponent
The second option is to write a similar function for testing. it will return a promise with a working link or an error.
async function testCesiumElemet(ref,i=0){
return new Promise((resolve, reject)=>{
//console.log()
if (ref.current?.cesiumElement) {
resolve (ref)
} else if (i<500){
i++;
setTimeout(()=>{
testCesiumElemet(ref, i).then(resolve).catch(reject)
},10)
}else {
reject (new Error(Waiting more than ${500*10/1000} seconds.
))
}
})
}
I think I got the same problem. Rolling back to version 1.16.1 as a workaround fixed it for me.
After reading several articles and using the forum, I came to the conclusion that the problem is the lack of checks during the first rendering and the lack of waiting for React to respond. The checks that I described earlier are redundant since they are built into the useRef and creatRef code by default. There is probably a bug in the resium code associated with the transition of cesium to asynchronous functions.
Because of this, I also have two windows rendering at the same time during the first launch.
I've also encountered this issue before.
I had to use ref.current?.cesiumElement.clock
which worked fine until upgrading to 1.17.2.
What solved this issue was actually making also cesiumElement
itself nullable, meaning changing to ref.current?.cesiumElement?.clock
.
Seems quite funny, but this conditional rendering actually gave the component the desired "re-render" which made the ref defined again.