Open ahmed-adly-khalil opened 3 years ago
@ahmed-adly-khalil are you assigning your ref
to the Globe component, as in this example?
https://github.com/vasturiano/react-globe.gl/blob/master/example/countries-population/index.html#L46
yes, here is my code:
import { useState, useEffect, useRef } from 'react';
import dynamic from 'next/dynamic';
const Globe = dynamic(import('react-globe.gl'), { ssr: false });
export default function Home() {
const globeEl = useRef();
// custom globe material
useEffect(() => {
console.log(globeEl.current);
}, []);
return (
<div className="bg-white">
<Globe
ref={globeEl}
backgroundColor={'rgba(0,0,0,0)'} width={500} height={500}
waitForGlobeReady={true}
globeImageUrl="/globe.png"
showAtmosphere={true}
atmosphereColor="blue"
atmosphereAltitude={0.15}
rendererConfig={{ antialias: true, alpha: true }}
/>
....
also here is my package.json
"dependencies": {
"next": "10.1.2",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-globe.gl": "^2.18.0",
"three": "^0.127.0"
},
and I'm getting this warning in the console, not sure if it's related
I tried to remove three
from the package but it gave an error that it's required
@ahmed-adly-khalil I've just made this minimal sandbox with a Globe ref injection, similar to your case: https://codesandbox.io/s/globe-ref-0p05z?file=/src/App.js
If you look in the console, you'll see that the component methods are available there, including .controls()
. If you do not observe the same, there might be an unrelated error on how your app setup.
The "multiple instances of Three" warning should not be an issue. It simply detects your app imported version, and the one included internally in the Globe component.
Ok, will look into it, the only thing I can think of now is next js and how it use refs
Thanks so much
This is Nextjs specific and no bug.
This is because server-side rendering doesn't have access to the window-object.
const Globe = dynamic(
() => import('react-globe.gl'),
{ ssr: false }
)
But then when you try to log the ref, the component methods are not available anymore.
On Nextjs it works, when you wrap globe in an own component, and then dynamic import that component from a higher one.
P.S. Great library btw
@ahmed-adly-khalil I was able to get it working with the following, instead of using Next.js dynamic import.
let Globe = () => null
if (typeof window !== 'undefined') Globe = require('react-globe.gl').default
This is Nextjs specific and no bug.
- If you import it normal, you have access to the methods - but you get window undefined on first pageload.
This is because server-side rendering doesn't have access to the window-object.
- Nextjs does have dynamic imports like so, after which you can load the Globe fine.
const Globe = dynamic( () => import('react-globe.gl'), { ssr: false } )
But then when you try to log the ref, the component methods are not available anymore.
On Nextjs it works, when you wrap globe in an own component, and then dynamic import that component from a higher one.
P.S. Great library btw
Can you please elaborate on it, I have wrapped the globe in my own components, still doesn't work..
I solve this issue with passing ref value as props. However, when I pass ref value with forwardRef, it does not work interestingly. Here is my version as example with next.js:
// server component
...
<Suspense fallback={<div>Loading...</div>}>
<WorldGlobeWithAutoRotate polygon={polygon} />
</Suspense>
...
// client component: WorldGlobe Wrapper
'use client';
import { useRef } from 'react';
import { GlobeMethods } from 'react-globe.gl';
import { PropsWorldGlobe } from '../worldGlobe.types';
import dynamic from 'next/dynamic';
const WorldGlobe = dynamic(() => import('..').then((mod) => mod.WorldGlobe), { ssr: false });
export const WorldGlobeWithAutoRotate = ({ polygon }: PropsWorldGlobe) => {
const globeEl = useRef<GlobeMethods>();
return (
<>
<WorldGlobe
polygon={polygon}
globeRef={globeEl}
/>
</>
);
};
// client component
'use client';
import * as THREE from 'three';
import { PropsWorldGlobe } from './worldGlobe.types';
import Globe from 'react-globe.gl';
import { useEffect } from 'react';
export const WorldGlobe = ({ polygon, globeRef }: PropsWorldGlobe) => {
const polygonsMaterial = new THREE.MeshLambertMaterial({ color: 'lightgray', side: THREE.DoubleSide });
useEffect(() => {
if (globeRef?.current) {
globeRef.current.controls().autoRotate = true;
globeRef.current.controls().autoRotateSpeed = 1.5;
globeRef.current.pointOfView({ lat: 50, lng: -80, altitude: 2 }, 7000);
}
}, [globeRef]);
return (
<>
<Globe
ref={globeRef}
animateIn={true}
backgroundColor='rgba(0,0,0,0)'
showGlobe={false}
showAtmosphere={false}
polygonsData={polygon}
polygonCapMaterial={polygonsMaterial}
polygonSideColor={() => 'rgba(0, 0, 0, 0)'}
width={500}
height={500}
/>
</>
);
};
One thing to note that I use server component to fetch the data instead of using useEffect. This also helps to mitigate the issue that "Window is not defined", which is caused when pre-rederngin client component in server. Hope this helps.
Hello, I'm using react-globe-gl with next JS and it's working fine for the most part, however i can't set auto rorate for the globe to any speed. in the ThreeGlobe library i was able to achieve this by doing
Globe.rotation.y += 0.005;
:However, in next i can't see any exposed property for this, also wheh i tried to access the exposed elements like
globeEl.current.controls()
it's always undefined.Here is a high level code:
also when tried
I got the following error
am I missing anything?