exportdefaultfunctionisBright(rgbCode) { let c = rgbCode.substring(1); let rgb = parseInt(c, 16); let r = (rgb >> 16) & 0xff; let g = (rgb >> 8) & 0xff; let b = (rgb >> 0) & 0xff;
let luma = 0.2126 * r + 0.7152 * g + 0.0722 * b;
return luma > 127 ? true : false; // true일경우 밝음, 아닐 경우 어두움 }
// Set up the interval. useEffect(() => { functiontick() { savedCallback.current(); } if (delay !== null) { let id = setInterval(tick, delay); return() =>clearInterval(id); } }, [delay]); }
setInterval + clearInerval의 단점
임피던스 불일치라는 용어를 쓴다. 리액트 프로그래밍 모델은 state를 기반으로 렌더링되고 기타 변수들을 관리한다.
하지만 setInterval은 일단 설정하고 나면 없애는 것 외에는 변경할 수 없다. 또한 react의 state 기반으로 동작하지도 않는다.
state나 props가 변하더라도 교체하기 전까지는 내부의 props와 state를 참조할 것이다.
ref의 사용
위에서 알아본 것 처럼 setInterval은 react의 동작과 다르게 동작한다. 이로 인해 발생하는 문제점은 다음과 같다.
첫 렌더에서 callback1을 가진 setInterval(callback1,delay)를 수행한다.
다음 렌더에서 새로운 props와 state를 거쳐서 만들어지는 callback2가 있다. 하지만 시간을 재설정하지 않고서는 callback을 대체할 수 없다.
이를 해결하려면 useRef를 사용하면 된다.
useRef는 hooks에서 렌더링과 관련없는 변수를 담는데에 이용되는 하나의 상자이다.
솔루션은 다음과 같다.
setInterval(fn,delay)에서 함수가 savedCallback을 호출하게 만든다.
// callback에 변경사항이 있을 경우 가장 최근의 함수를 저장한다 // 최근의 state나 props의 변경사항을 반영한 callback이다. useEffect(() => { savedCallback.current = callback; }, [callback]);
// 타이머를 교체하거나 하는 작업 없이 제일 최근에 들어온 함수를 실행한다. useEffect(() => { functiontick() { savedCallback.current(); } if (delay !== null) { let id = setInterval(tick, delay); return() =>clearInterval(id); } }, [delay]); }
Interval 일시정지하기
위의 useInterval hook에선 null을 delay에 전달하는 것으로 interval을 일시 정지할 수 있다. delay가 null이 아닐경우 타이머를 설정하기 떄문이다..!