이벤트 참여 버튼에는 클릭시 이벤트 참여 API를 요청하는 핸들러가 등록되어있습니다.
API 요청을 보내기 전에 버튼을 비활성화
하고, 응답을 받고 나서 활성화
하도록 로직을 구현했습니다.
하지만 원하는 대로 동작하지 않음을 확인할 수 있었습니다.
아래의 코드는 이벤트 참여 API 대신에 setTimeout
함수로 2초뒤에 fulfilled
된 promise를 반환하는 함수를 사용하여 상황을 가정하였습니다.
위 코드의 문제점은 버튼의 활성/비활성 상태를 지역 변수 let isDisable
로 관리했다는 것입니다.
리액트 컴포넌트는 props와 state의 변화를 감지하여 리렌더링을 진행합니다. 리액트는 지역 변수의 변화를 감지하지 못하기 때문에 리렌더링을 하지 못했고, 따라서 버튼이 비활성화가 되지 않았습니다.
이를 해결하기 위해서는 useState 나 redux와 같은 상태관리 툴을 사용해서 관리해주면 됩니다. useState로 생성한 상태의 변화는 리액트가 감지하여 리렌더링 해줄 수 있습니다.
하단의 코드처럼 isDisable
를 useState
로 상태로서 관리하였더니 정상적으로 동작함을 확인할 수 있었습니다.
하지만 useState 를 사용해서 버튼 비활성화 상태를 관리하더라도 정상 동작하지 않을 수 있습니다.
버튼 엘러먼트의 disabled 속성값에 비활성화 상태를 전달하지 않고,
API 요청 함수 안에서 isDisable이 true일 때 return 하는 방법으로 API 중복 요청을 방지하면 정상 동작하지 않습니다.
useState
를 사용해서 버튼 비활성화 상태를 관리하더라도 버튼 태그에게 직접 disable 상태를 전달해주지 않는 경우엔, useState
가 비동기로 동작하기 때문에 API가 여러번 호출 되는 것을 방지할 수 없었습니다.
따라서 useRef
를 사용해서 API 호출 활성화 상태를 관리하였습니다.
isDisableAPI.current
에 API 호출 활성화 상태를 저장하면 이는 동기적으로 동작하기 때문에 비활성화 상태를 즉각적으로 적용할 수 있었습니다.
꾸준하시네요 👍