# animate function is being called but not displayed

**URL:** <https://discourse.threejs.org/t/animate-function-is-being-called-but-not-displayed/51894>\
**Category:** Questions\
**Tags:** animation\
**Created:** [May 22, 2023, 10:14pm UTC](https://discourse.threejs.org/t/animate-function-is-being-called-but-not-displayed/51894 "2023-05-22T22:14:44Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![HerrKoolS](https://avatars.discourse-cdn.com/v4/letter/h/3be4f8/32.png) [@HerrKoolS](https://discourse.threejs.org/u/HerrKoolS)\
**Post date:** [May 22, 2023, 10:14pm UTC](https://discourse.threejs.org/t/animate-function-is-being-called-but-not-displayed/51894/1 "2023-05-22T22:14:44Z")

</div>

Hi, I got a react component that uses Three.js for displaying a globe consisting of an earthmesh and a cloudmesh. I have a function (const) called animate, that rotates the globe and updates the TrackingBallControls, which I use additionally. I also got a useState called selectedValue that can take different values. Whenever the selectedValue changes I want to stop the current animation and start a new one afterwards in order to be able to access changed values inside the animate function. Whenever I change the selectedValue the animation stops and is being called again as expected. However the rotation of the earthMesh as well as the controls are no longer being displayed. When logging the rotation of the earthMesh I’m seing the value being updated, but the animation is just not being shown/updated. I’m really desperate already because I just can’t seem to find the root cause of this and especially no solution. Can anyone tell me what im doing wrong here? Thank you in Advance!

```javascript

import React, { useState, useEffect, useRef } from 'react';
import axios from 'axios';
import './MainComponent.css';
import * as THREE from 'three';
import map from './assets/earth_living.jpg';
import bumpMap from './assets/elev_bump_8k.jpg';
import earth_clouds from './assets/fair_clouds_8k.jpg';
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls';
import CoordinateStorage from './CoordinateStorage';
import {Grid, Box} from '@mui/material';

const MainComponent = ({selectedTopic}) => {
  const [selectedValue, setSelectedValue] = useState(selectedTopic);
  const containerRef = useRef(); //Container für das 3D Model
  const modelCreatedRef = useRef(false);
  const earthMeshRef = useRef();
  const animationRef = useRef(null);

  var scene, camera, renderer, controls, canvas, material, cloudMaterial, light;
  var cloudGeometry, cloudMesh;
  var animationSpeed = 0.0005;

  useEffect(() => {
    setSelectedValue(selectedTopic);
    removeExistingLocations();
  }, [selectedTopic]);

  /**
   * Creates the 3D Model of the earth
   */
  const setup3DModel = () => {
    material = new THREE.MeshStandardMaterial();
    material.map = new THREE.TextureLoader().load(map)
    material.bumpMap = new THREE.TextureLoader().load(bumpMap);
    material.bumpScale = 0.2;

    cloudMaterial = new THREE.MeshPhongMaterial();
    cloudMaterial.map = new THREE.TextureLoader().load(earth_clouds);
    cloudMaterial.transparent = true;
    cloudMaterial.opacity = 0.3;
    cloudGeometry = new THREE.SphereGeometry(1.01, 32, 32);
    cloudMesh = new THREE.Mesh(cloudGeometry, cloudMaterial);

    light = new THREE.PointLight(0xffffff, 1);
    light.position.set(5, 0, 0);
    
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0x282c34);

    camera = new THREE.PerspectiveCamera(50, window.innerWidth/window.innerHeight, 1, 1000);
    camera.position.z = 2.8;

    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth * 0.65, window.innerHeight/1.5);
    camera.aspect = window.innerWidth * 0.65/(window.innerHeight/1.5);
    camera.updateProjectionMatrix();
    window.addEventListener('resize', function() {
      renderer.setSize( window.innerWidth * 0.65, window.innerHeight/1.5);
      camera.aspect = window.innerWidth * 0.65/(window.innerHeight/1.5);
      camera.updateProjectionMatrix();
    })

    canvas = renderer.domElement;

    document.body.appendChild(renderer.domElement);
    controls = new TrackballControls(camera, renderer.domElement);
    controls.minDistance = 2.1;
    controls.maxDistance = 8;
    controls.noPan = true;

    scene.add(light);
  }

  setup3DModel();

  const animate = () => {
    animationRef.current = requestAnimationFrame(animate);
    earthMeshRef.current.rotation.y += animationSpeed;
    cloudMesh.rotation.y += animationSpeed * 0.85;
    light.position.copy(camera.position);
    console.log(selectedValue);
    controls.update();

    
    renderer.render(scene, camera);
  }

const stopAnimation = () => {
  cancelAnimationFrame(animationRef.current);
};

  /**
   * Creates the cloud layer, adds Mouse Listeners to the canvas and defines animation function
   */
  const create3DModel = () => {
    const cylinderMaterial = new THREE.MeshBasicMaterial();
    // Erstelle eine Kugelgeometrie
    const geometry = new THREE.SphereGeometry(1, 32, 32);
    // erstelle wolken/kugel geometrie

    // erstelle eine zylindergeometrie
    const cylinderGeometry = new THREE.CylinderGeometry(0.01,0.01,0.5);
    // Erstelle ein Mesh-Objekt mit der Geometrie und dem Material
    earthMeshRef.current = new THREE.Mesh(geometry, material);
    //const cityMesh = new THREE.Mesh(cityGeometry, cityMaterial);
    const cylinderMesh = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
    
    //cancel mouse movement when rotating globe
    canvas.addEventListener('mousedown', function(event) {
      animationSpeed = 0;
    })

    //right-click listener for restarting the rotation animation after drag event
    canvas.addEventListener("contextmenu", function(event){
       // Verhindert das Öffnen des Kontextmenüs
      event.preventDefault();
      animationSpeed = 0.0005;
    });
    
cylinderMesh.position.set(translatedCoordinates[0],translatedCoordinates[1],translatedCoordinates[2]);
    scene.add(earthMeshRef.current);
    scene.add(cloudMesh);
    containerRef.current.appendChild(canvas);

  }

useEffect(() => {
    if (!modelCreatedRef.current) {
      create3DModel();
      modelCreatedRef.current = true;
    }
  }, []);

  useEffect(() => {
    fetchData();
    fetchPrice();
    stopAnimation();
    animate();
  }, [selectedValue]);

  useEffect(() => {
    const interval = setInterval(() => {
      fetchData();
      fetchPrice();
    }, 5 * 1000); //15 * 60 * 1000 to call every 15 minutes

    return () => {
      clearInterval(interval);
    };
  }, []);

  return (
    <div className='main-class'>
      <Grid container>
        <Grid item xs={6} ref={containerRef}></Grid>
        <Grid item xs={6}>
          <div>
            <label>{selectedValue}</label>
          </div>
        </Grid>
      </Grid>
    </div>
  );
}

export default MainComponent;

```

Here is a codesandbox link, where my problem can be reproduced:

> **[Earth rotation - CodeSandbox](https://codesandbox.io/s/earth-rotation-fcp210?file=%2Fsrc%2FMainComponent.js)**
>
> Earth rotation by pajuprojects using @emotion/react, @emotion/styled, @mui/material, axios, loader-utils, react, react-dom, react-icons, react-scripts

Steps to reproduce:

- Have a look into the console: Option 1 will be logged each frame when the animation started
- Now change the value of the Fitler field above to let’s say “Option 2”
- The animation stops but the value of “Option 2” is still being logged each frame, which means the animate function is being called correctly, but the effects of the value changes inside the animate function are just not being displayed/rendered

---

<div class="post-metadata">

**Author:** ![tfoller](https://avatars.discourse-cdn.com/v4/letter/t/3e96dc/32.png) [@tfoller](https://discourse.threejs.org/u/tfoller)\
**Post date:** [May 23, 2023, 2:14am UTC](https://discourse.threejs.org/t/animate-function-is-being-called-but-not-displayed/51894/2 "2023-05-23T02:14:11Z")

</div>

It will help if you provide a live example of your program on codepen or a similar platform and explain how to reproduce your issue.

---

<div class="post-metadata">

**Author:** ![HerrKoolS](https://avatars.discourse-cdn.com/v4/letter/h/3be4f8/32.png) [@HerrKoolS](https://discourse.threejs.org/u/HerrKoolS)\
**Post date:** [May 23, 2023, 10:03am UTC](https://discourse.threejs.org/t/animate-function-is-being-called-but-not-displayed/51894/4 "2023-05-23T10:03:57Z")

</div>

Hi, thanks for your reply. Here is a codesandbox link. I added the steps to reproduce to my question.

> **[Earth rotation - CodeSandbox](https://codesandbox.io/s/earth-rotation-fcp210?file=%2Fsrc%2FMainComponent.js)**
>
> Earth rotation by pajuprojects using @emotion/react, @emotion/styled, @mui/material, axios, loader-utils, react, react-dom, react-icons, react-scripts

---

<div class="post-metadata">

**Author:** ![tfoller](https://avatars.discourse-cdn.com/v4/letter/t/3e96dc/32.png) [@tfoller](https://discourse.threejs.org/u/tfoller)\
**Post date:** [May 23, 2023, 10:44am UTC](https://discourse.threejs.org/t/animate-function-is-being-called-but-not-displayed/51894/5 "2023-05-23T10:44:09Z")

</div>

I don’t do react but there are some react errors that you probably should fix first.

I see a problem here:

```javascript
  useEffect(() => {
    //fetchData();
    //fetchPrice();
    stopAnimation();
    animate();
  }, [selectedValue]);

```

the way your code is written, when you assign **animationRef.current** from **requestAnimationFrame** it is the ID of the next call of **animate** , not the currently executed one, so when you pass it to **cancelAnimationFrame** you might cancel the scheduled pass, not the current one, or you might cancel the current one but after the next one is scheduled. This might also end up having two animate loops running.

If you comment out

```javascript
   // stopAnimation();
  // animate();

```

and switch from option1 to option2, the earth keeps rotating.

---

<div class="post-metadata">

**Author:** ![HerrKoolS](https://avatars.discourse-cdn.com/v4/letter/h/3be4f8/32.png) [@HerrKoolS](https://discourse.threejs.org/u/HerrKoolS)\
**Post date:** [May 23, 2023, 11:30am UTC](https://discourse.threejs.org/t/animate-function-is-being-called-but-not-displayed/51894/6 "2023-05-23T11:30:02Z")

</div>

I know deleting those two lines will keep the earth rotation. The problem is that unless you stop the current animation and start a new one. The used values inside the animate function wont be updated. So when commenting out the two lines you just mentioned, you will see that the logging of the selected value inside of the animate function will always stay “Option 1”, regardless of whats actually selected.

---

<div class="post-metadata">

**Author:** ![tfoller](https://avatars.discourse-cdn.com/v4/letter/t/3e96dc/32.png) [@tfoller](https://discourse.threejs.org/u/tfoller)\
**Post date:** [May 23, 2023, 11:38am UTC](https://discourse.threejs.org/t/animate-function-is-being-called-but-not-displayed/51894/7 "2023-05-23T11:38:27Z")

</div>

I don’t think it has anything to do with animate loop or THREE, it’s a react issue.
