Photo by Mink Mingle on Unsplash

üREACT CUSTOM HOOKS

React Hooks — useTimeout and useInterval

JavaScript timer üzerinden kullandığımız 2 mekanizma bulunuyor. Bunlardan bir tanesi bir işlemi o anda değil de belli bir süre sonra yapılmasını istiyorsak kullandığımız Timeout ait fonksiyonlar,

setTimeout(callback, delay) -> id
clearTimeout(id)

Peki belli aralıklar ile sürekli çalışsın istiyor isek bu durumda Interval ait fonksiyonlar bulunur.

setInterval(callback, delay) -> id
clearInterval(id)

Peki biz bu fonksiyonları bir React bileşeninin içerisinde kullanmak istersek. useEffect içerisinde kullanmalıyız ve bunları bileşen unmount olurken veya useEffect bağlı bağımlılık yapısı değişirken unsubscribe etmemiz gerekiyor

unsubscribe derken → clearTimeout veya clearInterval çağrımlarından bahsediyorum.

setTimeout

useEffect(() => {
const id= setTimeout(() => {
console.log('It will run after 3 second!')
}, 3000);
return () => clearTimeout(id);
}, []);

setInterval

useEffect(() => {
const id= setInterval(() => {
console.log('It will run every 3 second!');
}, 3000);
return () => clearInterval(id);
}, []);

Bunları yapmadığımız durumda useEffect sideEffect uygulamamız içerisinde görebiliriz. Yani bileşenin o an render edilmemesine karşın veya useEffect yapısının değişmesine rağmen eski yapıyı kullanan etkilerin devam etmesi olur.

Bu durumu özetleyen basit bir uygulamaya bakalım. UIdev web sitesinden Wait şeklinde bir bileşen yazmışlar. Yani yukarıda bahsettiğimiz özelliği bir bileşenin gösterimini geciktiren bir bileşen üzerinden sunmuşlar.

function Wait ({ delay = 1000, placeholder, ui }) {
const [show, setShow] = React.useState(false)

React.useEffect(() => {
const id = window.setTimeout(() => {
setShow(true)
}, delay)

return () => window.clearTimeout(id)
}, [delay])

return show === true
? ui
: placeholder
}

Bu durumda her bileşen içerisinde yazmam gereken UI gizlenip gösterilmesi bilgisini bileşenlerin içerisinden çıkarıp soyutlamış olurum.
Aşağıdaki proje için örnek linki

https://onurdayibasi.dev/hooks-useeffect-02

Bu kısımda aslında Wait şeklinde bir bileşen yaptığımızda Comp1,Comp2,Comp3 içerisinde belli bir süre bekleyip gösterilmesi logic dışarıya taşımız olduk.

Peki istenen seviye bu mu ? Dan Abramov göre bir seviye daha bunu soyutlayabiliriz. Wait dışında show, hide dışında da setTimeout bağımlı bileşenler olabilir. Bu durumda nasıl bir yapı oluşturmalıyız. Dan yazmış olduğu Making setInterval Declarative with React Hooks kullanarak Custom Hook yazacağız.

function useTimeout(callback, delay) {
const savedCallback = useRef();

useEffect(() => {
savedCallback.current = callback;
});

useEffect(() => {
function tick() {
savedCallback.current();
}

if (delay !== null) {
let id = setTimeout(tick, delay);
return () => clearTimeout(id);
}
}, [delay]);
}


function Wait({ delay = 1000, placeholder, ui }) {
const [show, setShow] = useState(false)
useTimeout(() => setShow(true), delay)
return show === true
? ui
: placeholder
}

Bu durumda Wait bileşeninden Timeout logic soyutlamış olduk. useTimeout Custom Hook sayesinde kodumuz artık daha çok birbirinden soyut tekrar kullanılabilir hale geldi.

Count Down

Aynı örneği CountDown için yani geriye sayma bileşeni için düşünelim. Aşağıdaki örnekte useEffect etkileri anlaşılsın diye sağdaki konsola interval oluşma ve yok edilme durumlarını console.log ile bastırdım.

https://onurdayibasi.dev/hooks-useeffect-03

Bu örnekte setInterval yapısını öncelikle useInterval dönüştürüyoruz.

function useInterval(callback, delay) {
const savedCallback = useRef();

useEffect(() => {
savedCallback.current = callback;
});

useEffect(() => {
console.log('useInterval useEffect')
function tick() {
console.log('useInterval useTick')
savedCallback.current();
}


if (delay !== null) {
let id = setInterval(tick, delay);
console.log('create Interval:' + id)

return () => {
clearInterval(id)
console.log('destroy Interval:' + id)
};
}
}, [delay]);
}

Artık elimizde Interval soyut olarak kullanabilecek bir customHook sahibiz. → useInterval

Diğer yapmamız gereken bu useInterval kullanan CountDown bileşeni oluşturmak

function CountDown({ initialCount, downLimit, initalDelay = 1000, bgColor = 'transparent' }) {
const [count, setCount] = useState(initialCount);
const [delay, setDelay] = useState(null);
useInterval(() => {
const newValue = count - 1;
setCount(newValue)
if (newValue <= downLimit) setDelay(null);
}, delay);

return (
<div style={{ display: 'flex', backgroundColor: bgColor }}>{count}
<button onClick={() => setDelay(initalDelay)}>Start</button>
<button onClick={() => setDelay(null)}>Stop</button>
</div>
)
}

Yukarıda görüleceği gibi artık Wait ve CountDown bileşenleri içerisinde useEffect koduna gerek kalmadı çünkü bunları useInterval ve useTimeout ile soyutlaştırdık.

Örnek Projeler

Okumaya Devam Et 😃

Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store