Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent re-rendering #171

Open
kamami opened this issue Mar 28, 2024 · 1 comment
Open

Prevent re-rendering #171

kamami opened this issue Mar 28, 2024 · 1 comment

Comments

@kamami
Copy link

kamami commented Mar 28, 2024

I am using an interval to change the population of my HexTubes and make an animation happen. I also have some Arcs added to the globe. Now I noticed, that whenever I update popData in the interval the arcs disappear and reappear again -> The whole globe is re-rendering. How can I prevent this behavior?

"use client";
import { useRef, useEffect, useState } from "react";
import Globe from "react-globe.gl";


export default function World() {
  const globeEl = useRef();
  const [countries, setCountries] = useState({ features: [] });
  const [popData, setPopData] = useState([]);
  const [increasePop, setIncreasePop] = useState(true);

  const N = 20;
  const arcsData = [...Array(N).keys()].map(() => ({
    startLat: (Math.random() - 0.5) * 180,
    startLng: (Math.random() - 0.5) * 360,
    endLat: (Math.random() - 0.5) * 180,
    endLng: (Math.random() - 0.5) * 360,
    color: [
      ["red", "white", "blue", "green"][Math.round(Math.random() * 3)],
      ["red", "white", "blue", "green"][Math.round(Math.random() * 3)],
    ],
  }));

  useEffect(() => {
    fetch("ne_110m_admin_0_countries.geojson")
      .then((res) => res.json())
      .then(setCountries);

    setPopData([
      { lat: 49.0, lng: 10.0, pop: 800000, originalPop: 800000 },
      { lat: 49.5, lng: 10.8, pop: 700000, originalPop: 700000 },
      { lat: 49.5, lng: 9.3, pop: 680000, originalPop: 680000 },
      { lat: 49.0, lng: 9.0, pop: 650000, originalPop: 650000 },
      { lat: 48.5, lng: 9.5, pop: 630000, originalPop: 630000 },
      { lat: 48.5, lng: 10.5, pop: 600000, originalPop: 600000 },
      { lat: 49.0, lng: 11.0, pop: 520000, originalPop: 520000 },
      { lat: 49.5, lng: 11.5, pop: 440000, originalPop: 440000 },
      { lat: 49.5, lng: 8.5, pop: 360000, originalPop: 360000 },
      { lat: 49.0, lng: 8.0, pop: 280000, originalPop: 280000 },
      { lat: 48.5, lng: 8.5, pop: 200000, originalPop: 200000 },
      { lat: 48.5, lng: 11.5, pop: 120000, originalPop: 120000 },
      { lat: 49.0, lng: 12.0, pop: 50000, originalPop: 50000 },
    ]);
  }, []);

  useEffect(() => {
    // Auto-rotate
    globeEl.current.controls().enableZoom = false;
    globeEl.current.controls().autoRotate = true;
    globeEl.current.controls().autoRotateSpeed = 1;
  }, []);

  useEffect(() => {
    const intervalId = setInterval(() => {
      setPopData((currentData) =>
        currentData.map((data) => {
          const zufaelligerFaktor = Math.random() * (2 - 1.1) + 1.1; // Erzeugt einen Wert zwischen 1.1 und 2
          return {
            ...data,
            pop: increasePop ? data.originalPop * zufaelligerFaktor : 0, // Multipliziere originalPop mit dem zufälligen Faktor
          };
        })
      );
      setIncreasePop((prevState) => !prevState); // Wechsle den Zustand bei jedem Interval
    }, 2000); // Wechsle alle 2 Sekunden

    return () => clearInterval(intervalId);
  }, [increasePop, popData]);

  return (
    <Globe
      ref={globeEl}
      width={window.innerWidth - 64}
      backgroundColor="#fff"
      atmosphereColor="#f0f0f0"
      atmosphereAltitude={0.5}
      showGlobe={true}
      globeImageUrl="white.jpg"
      hexPolygonsData={countries.features}
      hexPolygonResolution={3}
      hexPolygonMargin={0.4}
      hexPolygonUseDots={false}
      hexPolygonColor={(d) =>
        d.properties.REGION_UN == ("Americas" || "Europe") ? "#dbdbdb" : "#000"
      }
      hexBinResolution={3}
      hexMargin={0.4}
      hexBinPointsData={popData}
      hexBinPointWeight="pop"
      hexAltitude={(d) => d.sumWeight * 6e-8}
      hexTopColor="#000"
      hexSideColor="#000"
      hexTransitionDuration={500}
      arcsData={arcsData}
      arcColor={"color"}
      arcDashLength={() => Math.random()}
      arcDashGap={() => Math.random()}
      arcDashAnimateTime={() => Math.random() * 4000 + 500}
    />
  );
}
Bildschirmaufnahme.2024-03-28.um.17.54.47.mov
@vasturiano
Copy link
Owner

@kamami I think the culprit of the issue is that you should memoize these methods:

arcDashLength={() => Math.random()}
arcDashGap={() => Math.random()}
arcDashAnimateTime={() => Math.random() * 4000 + 500}

Otherwise everytime your component rerenders, you're essentially passing new method instances to globe, indicating that you wish that functionality to change and start over.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants