Scene.pointerDown handler calling React state hook


I’m a total newbie in React and Babylon.js, so apologies in advance if this is something completely obvious.

I’m doing a small app that highlights meshes in a scene. I was able to do that easily, by casting a ray and then highlighting the mesh via HighlightLayer.

In order to unhighlight the mesh, I’ll need to check if it’s highlighted first, so I created a pickedObjects state in React:

const [pickedObjects, setPickedObjects] = useState([]);

The scene’s onPointerDown handler is a function that does the ray casting, and highlights or unhighlights the mesh.

The problem is that for some reason, calling setPickedObjects from the onPointerDown handler doesn’t change the state at all.

If I do:

function addToPicked() {
    console.log("Setting picked objects");
    setPickedObjects((oldPickedObjects) => [...oldPickedObjects, "AAA"]);    
    console.log("PickedObjects length = " + pickedObjects.length);
    for (let i = 0; i < pickedObjects.length; i++) {
      console.log("Obj #" + i + " = " + pickedObjects[i]);

and set the scene’s onPointerDown handler to addToPicked:

scene.onPointerDown = addToPicked;

the handler is called but the pickedObjects state never is updated:

Setting picked objects
PickedObjects length = 0

If I create a simple html button and set its onClick handler to AddToPicked, then everything works as expected, and I get the output:

Setting picked objects
PickedObjects length = 0
Setting picked objects
PickedObjects length = 1
Obj #0 = AAA
Setting picked objects
PickedObjects length = 2
Obj #0 = AAA
Obj #1 = AAA

Is there anything I need to do, when updating a React component’s state from a Babylon.js handler?

Thanks in advance,

Can you share the entire component with us? Nothing immediately jumps out to me but I am curious where you are calling this line: scene.onPointerDown = addToPicked;

Just figured this out.

React’s setState is async, which means that I shouldn’t be consulting the state immediately after, since there’s no guarantee that it’s updated (or valid).

I used useEffect and passed the state I want to check as a parameter, and I’m able to output the correct state there.

1 Like

I’m calling it on the onSceneReady handler of SceneComponent.

Even though I’m able to check the state in useEffect, this doesn’t solve my issue, because I can’t consult any state from within the onPointerDown handler.

Inside this handler all component states are either empty or null.

Any ideas?

Hello @alexr apologies for the delay in answering, did you manage to figure it out or would you like any help? :slight_smile:

Hi @carolhmj, thanks for your answer. No need to apologize, I was actually amazed to get an answer :slight_smile: .

Yes, apparently there are issues accessing React’s state from en event listener. My first approach was using useRef (Accessing React State in Event Listeners with useState and useRef hooks | by Bryan Grill | geographIT | Medium) but that was cumbersome.

Eventually I figured out that I could use HighlightLayer | Babylon.js Documentation to figure out if a mesh was highlighted and used that.

Thanks once again.

1 Like