Reputation: 100
I am trying to implement counter in React.js which increments the value continuously on click but I am not getting the appropriate result, code works fine in plain html/js.
https://codesandbox.io/s/autumn-wood-fhsjx?file=/src/App.js
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [value, setValue] = useState(0);
const continuosIncerment = () => {
console.log(`Setting ${value}`);
setValue(value + 1);
timer = setTimeout(function() {
continuosIncerment();
}, 1000);
};
function timeoutClear() {
clearTimeout(timer);
}
return (
<div className="App">
<button
onMouseLeave={timeoutClear}
onMouseUp={timeoutClear}
onMouseDown={continuosIncerment}
>
Increment
</button>
<div>Value = {value} </div>
</div>
);
}
Upvotes: 2
Views: 2747
Reputation: 31
I have solved continous counter without using useEffect and useRef. Simple solution check it.
`import { useState } from "react"
function App() {
let [count,setCount] = useState(0);
let [timerId,setTimerId] = useState("")
let start=()=>{
let id = setInterval(increment,1000)
setTimerId(id)
}
let increment=()=>{
setCount(count=>count+1)
}
let stop=()=>{
clearInterval(timerId)
}
return (
<>
<h1>Counter : {count}</h1>
<button onClick={start}>Start</button>
<button onClick={stop}>Stop</button>
</>
)
}
export default App`
Upvotes: 0
Reputation: 13
This is the code for a timer that I used on my app, maybe it can help you.
import React, { useState, useEffect } from "react";
import "./clock.css";
function Clock() {
const [isRunning, setIsRunning] = useState(false);
const [seconds, setSeconds] = useState(0);
const [minutes, setMinutes] = useState(0);
const [hours, setHours] = useState(0);
const toggleOn = () => {
setIsRunning(!isRunning);
};
const reset = () => {
setMinutes(0);
setSeconds(0);
setIsRunning(false);
setHours(0);
};
useEffect(() => {
let interval = null;
if (isRunning) {
interval = setInterval(() => {
setSeconds((seconds) => seconds + 1);
}, 1000);
if (seconds > 60) {
setMinutes((minutes) => minutes + 1);
setSeconds(0);
}
if (minutes > 60) {
setHours((hours) => {
return hours + 1;
});
setMinutes(0);
}
} else if (!isRunning && seconds !== 0) {
clearInterval(interval);
}
return () => clearInterval(interval);
}, [isRunning, seconds]);
const formatedTime = () => {
let formatedSeconds = seconds < 10 ? `0${seconds}` : seconds;
let formatedMinutes = () => {
if (hours >= 1) {
if (minutes < 10) {
return `0${minutes}`;
} else return minutes;
} else if (hours < 1) {
return minutes;
}
};
let formatedHours = hours < 1 ? " " : `${hours}:`;
let formatedTime = `${formatedHours}${formatedMinutes()}:${formatedSeconds}`;
return formatedTime;
};
return (
<div className="clock">
<h1>{formatedTime()}</h1>
<div>
<button className="btn btn-primary m-1" onClick={toggleOn}>
{isRunning ? "Pause" : "Start"}
</button>
<button className="btn btn-primary m-1" onClick={reset}>
Reset
</button>
</div>
</div>
);
}
export default Clock;
Upvotes: 1
Reputation: 13682
You can use setInterval
, useRef
and callback approach to update state to solve your issue.
Code snippet
export default function App() {
const [value, setValue] = useState(0);
const timer = useRef(null);
const increment = () => {
timer.current = setInterval(() => setValue(prev => prev + 1), 500);
};
function timeoutClear() {
clearInterval(timer.current);
}
return (
<div className="App">
<button
onMouseLeave={timeoutClear}
onMouseUp={timeoutClear}
onMouseDown={increment}
>
Increment
</button>
<div>Value = {value} </div>
</div>
);
}
Upvotes: 4