অন্যরা যেমন উল্লেখ করেছে, সমস্যাটি useState
কেবল একবার বলা হয় ( deps = []
অন্তর সেট আপ করার জন্য এটি:
React.useEffect(() => {
const timer = window.setInterval(() => {
setTime(time + 1);
}, 1000);
return () => window.clearInterval(timer);
}, []);
তারপরে, প্রতিবার setInterval
টিক্স দিলে, এটি আসলে কল করবে setTime(time + 1)
, তবে কলব্যাক (সমাপনীকরণ) সংজ্ঞায়িত হওয়ার পরে time
শুরুতে এটি সর্বদা মানটি ধরে রাখবে setInterval
।
আপনি useState
সেটার বিকল্প ফর্মটি ব্যবহার করতে পারেন এবং আপনি যে প্রকৃত মান সেট করতে চান তার চেয়ে কলব্যাক সরবরাহ করতে পারেন (ঠিক যেমন এর সাথে setState
):
setTime(prevTime => prevTime + 1);
তবে আমি আপনাকে নিজের useInterval
হুক তৈরি করতে উত্সাহিত করব যাতে আপনি setInterval
ঘোষক ব্যবহার করে আপনার কোডটি শুকান এবং সহজ করতে পারেন , যেমন ড্যান আব্রামভ এখানে প্রতিক্রিয়া হুক সহ সেট ইন্টেরালভাল ডিক্লারেটিভ তৈরির পরামর্শ দিয়েছেন :
function useInterval(callback, delay) {
const intervalRef = React.useRef();
const callbackRef = React.useRef(callback);
React.useEffect(() => {
callbackRef.current = callback;
}, [callback]);
React.useEffect(() => {
if (typeof delay === 'number') {
intervalRef.current = window.setInterval(() => callbackRef.current(), delay);
return () => window.clearInterval(intervalRef.current);
}
}, [delay]);
return intervalRef;
}
const Clock = () => {
const [time, setTime] = React.useState(0);
const [isPaused, setPaused] = React.useState(false);
const intervalRef = useInterval(() => {
if (time < 10) {
setTime(time + 1);
} else {
window.clearInterval(intervalRef.current);
}
}, isPaused ? null : 1000);
return (<React.Fragment>
<button onClick={ () => setPaused(prevIsPaused => !prevIsPaused) } disabled={ time === 10 }>
{ isPaused ? 'RESUME ⏳' : 'PAUSE 🚧' }
</button>
<p>{ time.toString().padStart(2, '0') }/10 sec.</p>
<p>setInterval { time === 10 ? 'stopped.' : 'running...' }</p>
</React.Fragment>);
}
ReactDOM.render(<Clock />, document.querySelector('#app'));
body,
button {
font-family: monospace;
}
body, p {
margin: 0;
}
p + p {
margin-top: 8px;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
}
button {
margin: 32px 0;
padding: 8px;
border: 2px solid black;
background: transparent;
cursor: pointer;
border-radius: 2px;
}
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
সহজ এবং ক্লিনার কোড উত্পাদন করা ছাড়াও, এটি আপনাকে স্বয়ংক্রিয়ভাবে পাস করার মাধ্যমে বিরতি দেওয়ার (এবং সাফ করা) অনুমতি দেয় এবং বিরতি আইডিও delay = null
ফেরত দেয়, যদি আপনি নিজে নিজে এটি বাতিল করতে চান (এটি ড্যানের পোস্টগুলিতে আচ্ছাদিত নয়)।
প্রকৃতপক্ষে, এটিকে আরও উন্নত করা যেতে পারে যাতে delay
বিরতিযুক্ত হলে এটি পুনরায় আরম্ভ না করে তবে আমি মনে করি বেশিরভাগ ব্যবহারের ক্ষেত্রে এটি যথেষ্ট ভাল good
আপনি যদি এর setTimeout
চেয়ে বেশি অনুরূপ উত্তর খুঁজছেন তবে এটি দেখুন setInterval
: https://stackoverflow.com/a/59274757/3723993 ।
এছাড়াও আপনি এর ঘোষণামূলক সংস্করণ খুঁজে পেতে পারেন setTimeout
এবং setInterval
, useTimeout
এবং useInterval
, প্লাস একটি কাস্টম useThrottledCallback
হুক মধ্যে টাইপ করা বিষয় লেখা https://gist.github.com/Danziger/336e75b6675223ad805a88c2dfdcfd4a ।