I'm confused how scope works in React.
I want to pass a value of a state to another state but what I'm finding is that in one function it prints the right value and in another it does not.
It's a countdown where a timer counts down and counts clicks, and at the very end, I want to get the total amount of clicks and send it to a state of total. So the states are:
const [strokeScore, setStrokeScore] = useState(1);
const [totalStrokeScore, setTotalStrokeScore] = useState(1);
const [strokeCountdown, setStrokeCountdown] = useState();
With strokeScore
being the clicks of the game - and I want to get that total and shoot it over to total stroke score.
For some reason I can't do that - what is going on here?
import React, { useEffect, useState } from 'react';
function ScoreCard() {
const [strokeScore, setStrokeScore] = useState(1);
const [totalStrokeScore, setTotalStrokeScore] = useState(1);
const [strokeCountdown, setStrokeCountdown] = useState();
const strokeCountdownDing = new Audio('/sounds/round-complete.mp3');
const endOfGameRound = () => {
strokeCountdownDing.play();
document.getElementById('stroke-counter-button').disabled = true;
}
const addToStrokeScore = () => {
setStrokeScore(strokeScore + 1);
// prints the correct number
console.log(strokeScore)
if (strokeCountdown === 0) {
endOfGameRound()
}
}
const subtractStrokeScore = () => {
setStrokeScore(strokeScore - 1);
}
const countDown = () => {
// let strokeCountdown = Math.floor(Math.random() * 31) + 100;
let strokeCountdown = 10
let strokeCountdownSpeedOptions = [1000, 500, 300, 200];
let strokeCountDownSpeed = strokeCountdownSpeedOptions[Math.floor(Math.random()*strokeCountdownSpeedOptions.length)];
let strokeCounter = setInterval(() => {
strokeCountdown--
// this is always giving me...1...?
console.log('the score is: ' + strokeScore)
setStrokeCountdown(strokeCountdown)
if (strokeCountdown === 0) {
endOfGameRound()
clearInterval(strokeCounter)
setTotalStrokeScore(strokeScore);
}
}, strokeCountDownSpeed)
}
useEffect(() => {
countDown();
}, []);
return (
<div className="gane__score-card">
<div className="gane__speed-level">
Speed: idk
</div>
<div className="gane__stroke-countdown">
Countdown: {strokeCountdown}
</div>
<p>Score: {strokeScore}</p>
<button id="stroke-counter-button" onClick={addToStrokeScore}>
{strokeCountdown === 0 ? 'Game Over' : 'Stroke'}
</button>
{/* window.location just temp for now */}
{strokeCountdown === 0
? <button onClick={() => window.location.reload(false)}>Play Again</button>
: <button disabled>Game in Progress</button>
}
<div className="gane__total-score">
Total score: {totalStrokeScore}
</div>
</div>
);
}
export default ScoreCard;
If you look at the sample above, I comment where it gives the correct number and where it seems to be stuck at "1" - why is this?
I tried as a different variable too.
import React, { useEffect, useState } from 'react';
function ScoreCard() {
const [strokeScore, setStrokeScore] = useState(1);
const [totalStrokeScore, setTotalStrokeScore] = useState(1);
const [strokeCountdown, setStrokeCountdown] = useState();
const strokeCountdownDing = new Audio('/sounds/round-complete.mp3');
// make new variable, maybe?
let strokeScoreCount = 0;
const endOfGameRound = () => {
strokeCountdownDing.play();
document.getElementById('stroke-counter-button').disabled = true;
}
const addToStrokeScore = () => {
setStrokeScore(strokeScore + 1);
// prints the correct number
console.log(strokeScore)
// but this just gives me zero?
strokeScoreCount = strokeScoreCount + 1;
console.log('maybe do a different var? : ' + strokeScoreCount)
if (strokeCountdown === 0) {
endOfGameRound()
}
}
const subtractStrokeScore = () => {
setStrokeScore(strokeScore - 1);
}
const countDown = () => {
// let strokeCountdown = Math.floor(Math.random() * 31) + 100;
let strokeCountdown = 10
let strokeCountdownSpeedOptions = [1000, 500, 300, 200];
let strokeCountDownSpeed = strokeCountdownSpeedOptions[Math.floor(Math.random()*strokeCountdownSpeedOptions.length)];
let strokeCounter = setInterval(() => {
strokeCountdown--
// this is always giving me...1...?
console.log('the score is: ' + strokeScore)
// this just gives me zero all the time? why?
console.log('the new variable to use is: ' + strokeScoreCount)
setStrokeCountdown(strokeCountdown)
if (strokeCountdown === 0) {
endOfGameRound()
clearInterval(strokeCounter)
setTotalStrokeScore(strokeScore);
}
}, strokeCountDownSpeed)
}
useEffect(() => {
countDown();
}, []);
return (
<div className="game__score-card">
<div className="game__speed-level">
Speed: idk
</div>
<div className="game__stroke-countdown">
Countdown: {strokeCountdown}
</div>
<p>Score: {strokeScore}</p>
<button id="stroke-counter-button" onClick={addToStrokeScore}>
{strokeCountdown === 0 ? 'Game Over' : 'Stroke'}
</button>
{/* window.location just temp for now */}
{strokeCountdown === 0
? <button onClick={() => window.location.reload(false)}>Play Again</button>
: <button disabled>Game in Progress</button>
}
<div className="game__total-score">
Total score: {totalStrokeScore}
</div>
</div>
);
}
export default ScoreCard;
Using a new variable just gives me zero all the time, and strokeScore is just permanently stuck at one in that function. But it's a state, can't you get state anywhere?
How do take value from one state, ensure it's correct in all scopes, and pass it to another state?
Note: the answer below explains state and scope but code breaks the setInterval. That question is here: useState with an argument in it's array is breaking a setInterval and makes it glitchy and erratic