반응형
이벤트 리스너 내부에서 상태를 접근하면 최신의 상태를 가져올 수 없습니다. 이벤트 리스너가 등록될 시점의 상태로만 접근이 가능합니다. 그렇다면, 최신의 상태를 가져오기위해서는 어떻게 해야할까요?
useRef를 이용해 이 문제를 해결 할 수 있습니다.
간단한 예제 프로그램을 만들어봤습니다.
화면에는 현재 count 상태 값을 출력하고, 버튼을 클릭하면 count 값을 1 증가시킵니다. 증가된 상태 값은 바로 적용되어 화면에 출력됩니다. 브라우저 화면을 더블 클릭하면 count 값을 alert 창에 출력하도록 이벤트 리스터도 추가했습니다.
import "./App.css";
import { useEffect, useState } from "react";
function App() {
const [count, setCount] = useState(0);
const incHandler = () => {
setCount(count + 1);
};
useEffect(() => {
window.addEventListener("dblclick", () => {
alert("count: " + count);
});
}, []);
return (
<div className="App">
<header className="App-header">
<p>{count}</p>
<button onClick={incHandler}>증가</button>
</header>
</div>
);
}
export default App;
여기서 바로 문제가 재현됩니다. count를 증가시키고 브라우저 화면을 더블클릭하여 count 값을 출력했는데, 현재 count 값과 다른 값이 출력되는 것을 확인할 수 있습니다.
이것은 이벤트가 등록되는 시점의 count 값을 복사하여 참조하고 있기 때문에 발생되는 문제입니다. 이를 해결하기 위해서는 useRef를 활용해야합니다.
import "./App.css";
import { useEffect, useRef, useState } from "react";
function App() {
const [count, _setCount] = useState(0);
const countRef = useRef(count);
const setCount = (value) => {
countRef.current = value;
_setCount(value);
};
const incHandler = () => {
setCount(count + 1);
};
useEffect(() => {
window.addEventListener("dblclick", () => {
alert("count: " + countRef.current);
});
}, []);
return (
<div className="App">
<header className="App-header">
<p>{count}</p>
<button onClick={incHandler}>증가</button>
</header>
</div>
);
}
export default App;
위와 같이 수정하면 됩니다. useRef 훅을 이용해 countRef 상태를 만들고, setCount할 때, countRef.current와 count 상태를 모두 변경합니다. 이벤트가 등록되는 시점에는 countRef의 참조값이 복사되기 때문에 countRef.current 값을 활용하면 최신의 상태를 유지할 수 있게 됩니다.
샘플 소스: https://github.com/hjleesm/test-useref
반응형
'React' 카테고리의 다른 글
Next.js v14 (0) | 2023.10.31 |
---|---|
React v18 (1) | 2023.10.30 |
[Recoil] Selectors 기본 알아보기 (0) | 2023.01.27 |
Recoil이란? (0) | 2023.01.24 |
[Next.js] create-next-app 환경에서 next.js, typescript, redux 세팅하기 (1) | 2021.10.15 |