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

useIntersect callback is not updated when the state changes #1057

Closed
fgarrec0397 opened this issue Sep 22, 2022 · 1 comment · Fixed by #1084
Closed

useIntersect callback is not updated when the state changes #1057

fgarrec0397 opened this issue Sep 22, 2022 · 1 comment · Fixed by #1084
Labels
bug Something isn't working released

Comments

@fgarrec0397
Copy link

  • three version: 0.144.0
  • @react-three/fiber version: 8.7.1
  • @react-three/drei version: 9.26.1
  • node version: 16.17.0
  • npm (or yarn) version: 8.15.0

Problem description:

I'm making a Flappybird clone where the bird is a poop and the tunnels are toilets and I use the useIntersect hook to detect when a toilet is on the screen to make sure those toilets that are already been passed are deleted.

So globally, I have an array of toilets that is frequently updated.

The problem is the callback sticks on the first array I init, because (I checked in the code) the useEffect is called only on the onMount.

Relevant code:

I don't have a sandbox because the project is kind of huge and the problem is straightforward, but you can find the issue [here](https://github.com/fgarrec0397/flappy-poop/blob/SetupToilets/app/src/Features/Widgets/Toilets/components/ToiletColumn.tsx#:~:text=const%20ref%20%3D-,useIntersect,-((visible)

Suggested solution:

To fix the issue locally, I just overrided the useIntersect hook and add the onChange callback to the useEffect dependencies array

import { addAfterEffect, addEffect } from "@react-three/fiber";
import { useEffect, useRef } from "react";
import { Mesh, Object3D } from "three";

function useIntersect(onChange: (visible: boolean) => void) {
    const ref = useRef<Mesh>(null);
    const check = useRef(false);
    const temp = useRef(false);
    useEffect(() => {
        const obj = ref.current;

        if (obj) {
            // Stamp out frustum check pre-emptively
            const unsub1 = addEffect(() => {
                check.current = false;
                return true;
            }); // If the object is inside the frustum three will call onRender

            const oldOnRender = obj.onBeforeRender;

            obj.onBeforeRender = () => (check.current = true); // Compare the check value against the temp value, if it differs set state

            const unsub2 = addAfterEffect(() => {
                if (check.current !== temp.current) onChange((temp.current = check.current));
                return true;
            });
            return () => {
                obj.onBeforeRender = oldOnRender;
                unsub1();
                unsub2();
            };
        }
    }, [onChange]); // here

    return ref;
}

export { useIntersect };

@github-actions
Copy link

github-actions bot commented Oct 7, 2022

🎉 This issue has been resolved in version 9.34.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working released
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant