React

[React] 이벤트 리스너에서 현재 상태가져오기

코딩하는 Jay 2023. 6. 20. 17:32
반응형

사진: Unsplash 의 Luke Stackpoole

 이벤트 리스너 내부에서 상태를 접근하면 최신의 상태를 가져올 수 없습니다. 이벤트 리스너가 등록될 시점의 상태로만 접근이 가능합니다. 그렇다면, 최신의 상태를 가져오기위해서는 어떻게 해야할까요?

 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

 

GitHub - hjleesm/test-useref

Contribute to hjleesm/test-useref development by creating an account on GitHub.

github.com

참고: https://medium.com/geographit/accessing-react-state-in-event-listeners-with-usestate-and-useref-hooks-8cceee73c559

 

Accessing React State in Event Listeners with useState and useRef hooks

If you’re using React hooks in a component with an event listener, your event listener callback cannot access the latest state. We can…

medium.com

 

반응형

'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