I was building UI for a dictionary which shows a word followed by its meaning. In the below code I’m setting up the setInterval
initially and then on some events. I’m just focused on initial setInterval
.
Although I’m quite experienced in React but I am still not able to grab my head around why the setInterval
works when inside useEffect
hook but not from the if condition.
To replicate just comment out the if condition and uncomment useEffect
block.
Can someone please explain?
import React, { useState, useEffect } from 'react';
import Dictionary from './Dictionary.json';
import './App.css';
const words = Object.keys(Dictionary);
let currentInterval;
function App() {
const [randomWord, setRandomWord] = useState(words && words[Math.round(Math.random() * words.length)]);
const [wordGenerationDuration, setWordGenerationDuration] = useState(10000);
function selectRandomWord() {
setRandomWord(words[Math.round(Math.random() * (words.length - 1))]);
}
if(!currentInterval) {
currentInterval = setInterval(selectRandomWord, wordGenerationDuration);
}
// useEffect(
// () => {
// currentInterval = setInterval(selectRandomWord, wordGenerationDuration);
// }, []
// )
return (
<div className='App'>
<div className='dictionary-wrapper'>
<p className='dictionary-word'>
{randomWord}
</p>
<p className='dictionary-meaning'>
{Dictionary[randomWord]}
</p>
<p className='next-button cursor-pointer'>
<span
onClick={
() => {
clearInterval(currentInterval);
selectRandomWord();
currentInterval = setInterval(selectRandomWord, wordGenerationDuration);
}
}
>
Next Word
</span>
</p>
<p>
<span>Auto Switch Duration:</span>
<input
className='dictionary-input'
type='number'
placeholder={wordGenerationDuration / 1000}
onChange={
(evt) => {
const wordGenerationDuration = Math.max(evt.target?.value * 1000, 10000);
clearInterval(currentInterval);
setWordGenerationDuration(wordGenerationDuration);
currentInterval = setInterval(selectRandomWord, wordGenerationDuration);
}
}
min='10'
/>
</p>
</div>
</div>
);
}
export default App;