Can I generate a value per second with React? - reactjs

Is there a way I can generate multiple SET VALUES per second using react?
What am I trying to accomplish?
I have created this "tap game" where you could generate $1 per tap up to $250 per tap depending on where you tap. In this game I want to be able to "hire employees." After designating the hired employee to, lets say "$1 team", my "Score" will increase by 1 per second. If I decided to hire another employee and I decided to assign it to "$5 team", it would increase by 5. Since I have 2 employees at this time, I do not want to cancel one or the other out, I would like them to run simultaneously (e.g. 6 per second in this example).
What Have I tried?
I have not tried, or tested, anything specifically because of course I am unsure of how to accomplish this. I have researched other Stack Overflow examples and I have came across one very similar, however, they are using an API where as I am not. Stack Overflow Example I am not sure if I would even need an API, I would assume I would not?
Request:
If at all possible, a solution that I could use dynamically would be extremely appreciated. If I decided to hire 10 employees and stick them all on $1 team, I would like to be able to do so.
Attached is a fully functional code.
import React, {useState, useEffect} from 'react'
const App = () => {
// ======================================
// HOOKS
// ======================================
const [score, setScore] = useState(0)
const [showEZBake, setShowEZBake] = useState(false)
const [showToasterOven, setShowToasterOven] = useState(false)
const [showConvectionOven, setShowConvectionOven] = useState(false)
const [showSmallFactory, setShowSmallFactory] = useState(false)
// ======================================
// FUNCTIONS
// ======================================
const winCondition = () => {
if (score >= 100000) {
return (
<h1>YOURE A WINNER!!</h1>
)
}
}
// EARN REVENUE FUNCTIONS
const earn1 = () => {
setScore(score + 1)
winCondition()
}
const earn5 = () => {
setScore(score + 5)
winCondition()
}
const earn25 = () => {
setScore(score + 25)
winCondition()
}
const earn50 = () => {
setScore(score + 50)
winCondition()
}
const earn250 = () => {
setScore(score + 250)
winCondition()
}
// PURCHASE ITEMS FUNCTIONS
const buyEZOven = () => {
setScore(score - 25)
}
const buyToasterOven = () => {
setScore(score - 250)
}
const buyConvectionOven = () => {
setScore(score - 1000)
}
const buySmallFactory = () => {
setScore(score - 15000)
}
const upgradeEZOven = () => {
if (score >= 25) {
setShowEZBake(true)
buyEZOven()
}
}
const upgradeToasterOven = () => {
if (score >= 250 ) {
setShowToasterOven(true)
buyToasterOven()
}
}
const upgradeConvectionOven = () => {
if (score >= 1000) {
setShowConvectionOven(true)
buyConvectionOven()
}
}
const upgradeSmallFactory = () => {
if (score >= 15000) {
setShowSmallFactory(true)
buySmallFactory()
}
}
// ======================================
// DISPLAY
// ======================================
return (
<div>
<h1>Bakery</h1>
<h2>Revenue {score}</h2>
<h3>No Bake Pudding</h3><button onClick={earn1}>$1</button>
{/* EZ BAKE OVEN */}
{showEZBake ? (
<>
<h3>Easy Bake Oven</h3>
<button onClick={earn5}>$5</button>
</>
) : (
<>
<h3>Purchase Easy Bake Oven</h3>
<button onClick={upgradeEZOven}>$25</button>
</>
)
}
{/* TOASTER OVEN */}
{showToasterOven ? (
<>
<h3>Toaster Oven</h3>
<button onClick={earn25}>$25</button>
</>
) : (
<>
<h3>Purchase Toaster Oven</h3>
<button onClick={upgradeToasterOven}>$250</button>
</>
)}
{/* CONVECTION OVEN */}
{showConvectionOven ? (
<>
<h3>Convection Oven</h3>
<button onClick={earn50}>$50</button>
</>
) : (
<>
<h3>Purchase Convection Oven</h3>
<button onClick={upgradeConvectionOven}>$1000</button>
</>
)}
{/* FACTORY */}
{showSmallFactory ? (
<>
<h3>Small Factory Production</h3>
<button onClick={earn250}>$250</button>
</>
) : (
<>
<h3>Purchase Small Factory</h3>
<button onClick={upgradeSmallFactory}>$15,000</button>
</>
)}
{/* WIN CONDITION */}
{
winCondition()
}
</div>
)
}
export default App

You can generate a value every second pretty easily with useEffect:
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setTimeout(() => {
setCount(count + 1);
}, 1000);
return () => clearTimeout(timer);
}, [count, setCount]);

Related

How to install audio in React?

I am using a package called npm i --save react-audio-player and I am trying to use to have music auto play when the page is loaded. At this time, I am able to get the audio player to display, so the package is installed properly, however, the music does not show up at all.
I have had my audio directory both inside, and outside of the the project directory and I have copied the path directly from vscode, but it does not show to be active. Im not exactly sure what could possibly be causing this error. At first I thought maybe it was just chrome blocking the autoplay, but that would not explain why the audio file is displaying at all.
Below is both my code and a photo of my files
import React, {useState, useEffect} from 'react'
import ReactAudioPlayer from 'react-audio-player'
const App = () => {
// ======================================
// HOOKS
// ======================================
const [score, setScore] = useState(0)
const [showEZBake, setShowEZBake] = useState(false)
const [showToasterOven, setShowToasterOven] = useState(false)
const [showConvectionOven, setShowConvectionOven] = useState(false)
const [showSmallFactory, setShowSmallFactory] = useState(false)
// const [counter, setCounter] = useState(score)
// ======================================
// FUNCTIONS
// ======================================
const winCondition = () => {
if (score >= 100000) {
return (
<h1>YOURE A WINNER!!</h1>
)
}
}
// EARN REVENUE FUNCTIONS
const earn1 = () => {
setScore(score + 1)
winCondition()
}
const earn5 = () => {
setScore(score + 5)
winCondition()
}
const earn25 = () => {
setScore(score + 25)
winCondition()
}
const earn50 = () => {
setScore(score + 50)
winCondition()
}
const earn250 = () => {
setScore(score + 250)
winCondition()
}
// PURCHASE ITEMS FUNCTIONS
const buyEZOven = () => {
setScore(score - 25)
}
const buyToasterOven = () => {
setScore(score - 250)
}
const buyConvectionOven = () => {
setScore(score - 1000)
}
const buySmallFactory = () => {
setScore(score - 15000)
}
// THIS IS AN EXAMPLE OF HOW TO FORCE TEXT ONTO A PAGE
// const reveal = () => {
// // If the score is greater than or equal to 5, return the <h1> element
// if (score >= 5) {
// return (
// <h1>TEST</h1>
// )
// } else {
// // Otherwise, return null
// return null
// }
// }
const upgradeEZOven = () => {
if (score >= 25) {
setShowEZBake(true)
buyEZOven()
}
}
const upgradeToasterOven = () => {
if (score >= 250 ) {
setShowToasterOven(true)
buyToasterOven()
}
}
const upgradeConvectionOven = () => {
if (score >= 1000) {
setShowConvectionOven(true)
buyConvectionOven()
}
}
const upgradeSmallFactory = () => {
if (score >= 15000) {
setShowSmallFactory(true)
buySmallFactory()
}
}
// useEffect(() => {
// const timer = setInterval(() => {
// setCounter((prevCounter) => prevCounter + 1)
// }, 1000)
// return () => clearTimeout(timer);
// }, [counter, setCounter])
// ======================================
// DISPLAY
// ======================================
return (
<div>
<ReactAudioPlayer
src='../audio/mainMusic.mp3'
autoPlay
controls
/>
<h1>Bakery</h1>
<div className='header-grid-container'>
<h2>Revenue ${score}</h2>
<h2>Goal: $100,000</h2>
</div>
<div className='grid-container'>
{/* EZ BAKE OVEN */}
<img src="https://i.imgur.com/gDIbzJa.png" onClick={earn1}></img>
{showEZBake ? (
<img src="https://i.imgur.com/NQ0vFjF.png" onClick={earn5}></img>
) : (
<img onClick={upgradeEZOven} src="https://i.imgur.com/mwp9tL5.png"></img>
)}
{/* TOASTER OVEN */}
{showToasterOven ? (
<img src='https://i.imgur.com/k5m7lCM.png' onClick={earn25}></img>
) : (
<img src='https://i.imgur.com/hg12R4H.png' onClick={upgradeToasterOven}></img>
)}
{/* CONVECTION OVEN */}
{showConvectionOven ? (
<img src='https://i.imgur.com/JEzQkHL.png' onClick={earn50}></img>
) : (
<img src='https://i.imgur.com/x7i3ZeE.png' onClick={upgradeConvectionOven}></img>
)}
</div>
<div className='grid-container2'>
{showSmallFactory ? (
<img className='factory' src='https://i.imgur.com/HugCDVu.png' onClick={earn250}></img>
) : (
<img className='factory' src='https://i.imgur.com/HLsiH2r.png' onClick={upgradeSmallFactory}></img>
)}
{/* WIN CONDITION */}
{
winCondition()
}
{/* THIS IS AN EXAMPLE OF HOW TO CALL A FUNCTION
{
reveal()
} */}
</div>
</div>
)
}
export default App
Browsers does not allow pages to play audio unless there was a interaction done on the domain playing the sound. For Chrome this is the case since 2018.
Shown here: https://developer.chrome.com/blog/autoplay/
I am not familiar with package you are using, but I doubt it would change it. This means that you should not be able to play audio as soon as page is loaded and will have to force user to make any sort of interaction.
Aside from that I feel like the path is wrong. If you use those sort of relative paths and do not use import to get the resource they are in 90% instances resolved relative to public folder an project structure. So I'd try placing your audio folder into public and change src so that you are grabbing it relative to what browser sees. I sadly do not remember if that's public/audio/mainMusic.mp3 or audio/mainMusic.mp3or something else, but the simple test is, if you paste it into browser, it will either open, or start downloading the file.

How to swipe card programatticaly in react using react-tinder card

I am fetching data from the Backend and loading them in the card using react-tinder-card
Swiping works properly but unable to swipe using the buttons
I follow the documentation but still did not work
Here is the sample
Swiping gestures are working fine.
But when implement by checking documentation things did not work
Things are not working and tomorrow is my project day
import React, { useEffect, useState, useContext, useRef } from "react";
function Wink() {
const [people, setPeople] = useState([]);
const [loading, setLoading] = useState(false);
const [currentIndex, setCurrentIndex] = useState(people.length - 1)
const [lastDirection, setLastDirection] = useState()
// used for outOfFrame closure
const currentIndexRef = useRef(currentIndex)
const childRefs = useMemo(
() =>
Array(people.length)
.fill(0)
.map((i) => React.createRef()),
[]
)
const updateCurrentIndex = (val) => {
setCurrentIndex(val)
currentIndexRef.current = val
}
const canGoBack = currentIndex < people.length - 1
const canSwipe = currentIndex >= 0
// set last direction and decrease current index
const swiped = (direction, nameToDelete, index) => {
setLastDirection(direction)
updateCurrentIndex(index - 1)
}
const outOfFrame = (name, idx) => {
console.log(`${name} (${idx}) left the screen!`, currentIndexRef.current)
// handle the case in which go back is pressed before card goes outOfFrame
currentIndexRef.current >= idx && childRefs[idx].current.restoreCard()
// TODO: when quickly swipe and restore multiple times the same card,
// it happens multiple outOfFrame events are queued and the card disappear
// during latest swipes. Only the last outOfFrame event should be considered valid
}
const swipe = async (dir) => {
if (canSwipe && currentIndex < db.length) {
await childRefs[currentIndex].current.swipe(dir) // Swipe the card!
}
}
// increase current index and show card
const goBack = async () => {
if (!canGoBack) return
const newIndex = currentIndex + 1
updateCurrentIndex(newIndex)
await childRefs[newIndex].current.restoreCard()
}
useEffect(() => {
setLoading(true);
axios
.post("http://localhost:4000/api/all-profile", { email })
.then(function (response) {
setPeople(response.data);
setCurrentIndex(response.data.length);
}
}, []);
return (
<div className="DateMainDiv">
<Header />
<div className="ProfieCards">
{people.map((person) => (
<TinderCard
className="swipe"
key={person.email}
ref={childRefs[index]}
preventSwipe={swipe}
onSwipe={(dir) => swiped(dir, person.name, person.email)}
onCardLeftScreen={onCardLeftScreen}
onCardUpScreen={onCardUpScreen}
>
<div
style={{ backgroundImage: `url(${person.image})` }}
className="Winkcard"
>
<img
onLoad={handleLoad}
src={person.image}
alt="Image"
className="TinderImage"
/>
<h3>
{person.name}{" "}
<IconButton
style={{ color: "#fbab7e" }}
onClick={() => handleOpen(person.email)}
>
<PersonPinSharpIcon fontSize="large" />
{parseInt(person.dist/1000)+"KM Away"}
</IconButton>
</h3>
</div>
</TinderCard>
))}
<SwipeButtonsLeft onClick={()=>{swipe("left")}} />
<SwipeButtonsLeft onClick={()=>{goback()}} />
<SwipeButtonsLeft onClick={()=>{swipe("right")}} />
</div>
</div>
);
}
export default Wink;

Prevent fetching when component re-renders

I have this simple website where I fetch data and get an array of Obj, and display it on the Quiz page, but I also implement a countdown. The problem is that every time the timer renders the fetch run again and I get a different array every sec. How Do I prevent the initial obj I fetch from changing?
Im getting the fetch array from useContext
const Quiz = () =>{
useEffect(() => {
countDown();
}, [num]);
let timer;
const countDown = () => {
if (num > 0) {
timer = setTimeout(() => {
setNum(num - 1);
}, 1000);
}
if(num === 0){
nextQuestion()
}
return num;
};
return(...)
}
You need to remove the num from the dependency array of useEffect.
When you add a dependency to useEffect it will re render every time it changes, and you only want countDown to run once.
Usually you should also wrap the countDown component with useCallback and put the countDown as a dependency on the useEffect
anyway, for now this should solve your issue -
const Quiz = () =>{
useEffect(() => {
countDown();
}, []);
let timer;
const countDown = () => {
if (num > 0) {
timer = setTimeout(() => {
setNum(num - 1);
}, 1000);
}
if(num === 0){
nextQuestion()
}
return num;
};
return(...)
}
does this answer your question ?
import React, { useState, useEffect } from "react";
const questionsList = [
{ question: "Sum of 4+4 ?" },
{ question: "Sum of 10+10 ?" }
];
export default function CountDown() {
const [counter, setCounter] = useState(10);
const [currentQuestion, setCurrentQuestion] = useState(0);
useEffect(() => {
const timeInterval = setInterval(() => {
counter > 0 && setCounter((prevCount) => prevCount - 1);
}, 1000);
if (counter === 0 && currentQuestion + 1 !== questionsList.length) {
setCurrentQuestion((prevQues) => prevQues + 1);
setCounter(10);
}
return () => {
clearInterval(timeInterval);
};
}, [counter]);
return (
<>
<h1>CountDown {counter}</h1>
<h1>
{counter !== 0 ? (
<>
{" "}
Question number {currentQuestion + 1}
{" --> "}
{questionsList?.[currentQuestion]?.question}
</>
) : (
<h1>Test Ended </h1>
)}
</h1>
</>
);
}

Why is the min state getting updated 2 times instead of only once?

Why is the min state getting updated in the multiples of two instead of just updating by one after every 59 seconds? How do I fix it?
import { useRef, useState } from "react";
export const Timer = () => {
const [second, setSecond] = useState(0);
const [min, setMin] = useState(0);
const watch = useRef(null);
const startTimer = () => {
watch.current = setInterval(() => {
setSecond((value) => {
if (value === 59) {
setSecond(0);
setMin((v) => v + 1);
}
return value + 1;
});
}, 1000);
};
return (
<div>
<h1>
{min}:{second}{" "}
</h1>
<button onClick={startTimer}>Start</button>
<button onClick={() => clearInterval(watch.current)}>Pause</button>
<button
onClick={() => {
setSecond(0);
return clearInterval(watch.current);
}}
>
Reset
</button>
</div>
);
};
This is the component as a whole. I am new to react so please help.

(reactjs) useEffect didn't run in background

I'm new to reactjs and and trying to make this simple stopwatch. this code is work in my browser, however when I minimize the browser the time paused, and only continue when I open the browser, do you found something I must be missed? Thanks in advance!
import { useState, useEffect } from "react";
export const SW = () => {
const [mSec, setMSec] = useState(0);
const [sec, setSec] = useState(0);
const [min, setMin] = useState(0);
const [isOn, setIsOn] = useState(false);
const start = () => setIsOn(true);
const stop = () => setIsOn(false);
const reset = () => {
setIsOn(false);
setMin(0);
setSec(0);
setMSec(0);
};
useEffect(() => {
let ms;
if (isOn) {
ms = setInterval(() => setMSec((mSec) => mSec + 1), 10);
if (sec === 59) {
setSec(0);
setMin((min) => min + 1);
}
if (mSec === 99) {
setMSec(0);
setSec((sec) => sec + 1);
}
}
return () => {
clearInterval(ms);
};
}, [mSec, sec, isOn]);
return (
<div>
<p>
{min.toString().padStart(2, "0")}:{sec.toString().padStart(2, "0")}:
{mSec.toString().padStart(2, "0")}
</p>
{!isOn && <button onClick={start}>{!mSec ? "start" : "resume"}</button>}
{isOn && <button onClick={stop}>stop</button>}
<button disabled={!mSec} onClick={reset}>
reset
</button>
</div>
);
};
It's not an issue on useEffect or your code, simply it's how browsers work, they execute JavaScript on the active tabs.
The solution is to use Web Workers API to execute JavaScript in the background.
For more details:
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
https://www.w3schools.com/html/html5_webworkers.asp

Resources