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

Tracking score #42

Open
oliverjam opened this issue Aug 11, 2021 · 3 comments
Open

Tracking score #42

oliverjam opened this issue Aug 11, 2021 · 3 comments

Comments

@oliverjam
Copy link

export default function LearnLoop() {
const webcamRef = useRef(null);
const canvasRef = useRef(null);
const [step, setStep] = useState(0);
let score = 0;
useEffect(() => {

Right now you're using a regular JS variable to keep track of the score. You're mutating this variable (to increase it by 1) when the user does some pose (I think):

if (
(step === 1 &&
pose.keypoints[9].position.y < topy + 250 &&
pose.keypoints[9].position.x < leftx + 100 &&
leftx < pose.keypoints[9].position.x) ||
(step === 1 &&
pose.keypoints[9].position.y < topy + 250 &&
leftx + 500 < pose.keypoints[9].position.x &&
pose.keypoints[9].position.x < leftx + 640)
) {
wendiv.style.borderColor = "green";
score++;

I might be wrong but it doesn't look like you're actually using score anywhere yet. If you do you'll probably see that the page doesn't update to show the new score. This is because React components only re-render when their props or state values change. If you mutate a regular variable React has no idea that it happened, so it won't update your component.

You need to put the score into state so React re-renders the component when it changes.

Once you've done that you'll find the useEffect dependency warning is important. If you don't list score as a dependency the effect won't re-run when the score changes. This means it will be stuck with whatever the first value of score was (when the effect was set up). Here's a simpler example:

function Counter() {
  const [score, setScore] = React.useState(0);
  React.useEffect(() => {
    setInterval(() => {
      setScore(score + 1);
    }, 1000)
  }, [])
  return (
    <div>{score}</div>
  );
}

if you run this you'll see the page update from 0 to 1, then stop. This is because when the useEffect callback was created the value of score was 0. So it is continually running setScore(0 + 1) over and over.

There are two ways to fix this: either add score to the effect's dependency array, which will re-run everything every time the score changes. This can be dangerous though since there might be stuff you don't want to run again and again (and you have to think about cleaning up your event listeners, intervals etc).

The simpler way is to use the "function updater" version of set state: setScore(oldScore => oldScore + 1). Now updating the score doesn't depend on any outside values, so it will always be correct, and ESLint will stop complaining about missing dependencies 😅

More info here: https://overreacted.io/a-complete-guide-to-useeffect/#dont-lie-to-react-about-dependencies

@oliverjam
Copy link
Author

Oh sorry I totally missed that you were using DOM manipulation to update a <p> with the score directly. This does work right now, since your component renders once, then keeps mutating the same score variable over and over.

However there is a big potential bug—as soon as your component re-renders (i.e. if any prop or state value changes) then score will be recreated as 0 again. (since the whole component function runs again, including let score = 0. The only way to keep track of values across different renders is using state or refs)

I would strongly recommend relying on props/state and returning JSX to keep your UI up-to-date (this is the "React way") rather than using DOM manipulation to try and manually keep the UI correct.

@oliverjam
Copy link
Author

But if this works right now and you're presenting today I would probably not worry about doing a whole load of refactoring (since you might break things, and I'm sure you have better things to spend your time on 😄)

@maryamgh1988
Copy link
Contributor

Amazing. I understand now. Exactly if I add another step to the game that score will get zero, but at the moment that score is the end of the game for the MVP of the project. Thanks.
Yes, we work on the presentation.

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