배경🎈
우리는 웹에서 버튼을 클릭했지만 응답이 즉각처리 오지 않아 고장난 줄 알고 여러번 클릭한 적이 있을 것이다.
이런 경우 내가 원치는 않지만 어떤 액션이 여러번 실행 될 수 있다! 그리고 그 액션이 예를들어 결재라는가 메시지를 보낸다는가 하는 치명적인 경우일 수 있다는 생각이 들었고 이를 방지하기 위해 해당기능을 구현하고자 한다.
어떤방식?🤔
일단 우리의 척척박사 챗지피티한테 물어봤는데 클릭하는 순간 state를 통해 button을 disabled 상태로 만든 뒤 setTimeout을 통해 1초 뒤에 다시 disabled를 풀라는데 ... 이건 굉장히 단순하고 비효율적인 방식이다. 사실 어떤 클릭을 통한 액션이 실행되기까지 1초 안팍이라고 단정 지을 수 없기 때문이다! 그리고 오히려 1초보다도 훨씬 클릭을 통한 액션이 수행 될 수 있다.
그래서!!! 고민고민 하다 try/catch 문을 이용하면 되겠다는 생각이 들었다!!
try, catch를 이용하면 클릭 액션으로 api의 성공/실패 결과를 확인 시점에을 캐치 할 수 있을 것 같았다!
그리하여 .... 구현을 완성했다!
구현해봅시다!💻
일단 Button Component를 정의했다.
import { ButtonHTMLAttributes, useState } from 'react'
interface IButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
size?: 's' | 'm' | 'l'
shape?: 'square' | 'normal' | 'rounded'
children: React.ReactNode
clickEvent: () => Promise<void>
}
const BUTTON_SHAPE = {
square: {
borderRadius: '0px',
},
normal: {
borderRadius: '4px',
},
rounded: {
borderRadius: '30px',
},
} as const
/** 버튼 사이즈 별 style 기재 */
const BUTTON_SIZE = {
s: {
fontSize: '13px',
padding: '4px 10px',
},
m: {
fontSize: '14px',
padding: '6px 16px',
},
l: {
fontSize: '15px',
padding: '7px 21px',
},
} as const
const Button = ({
shape = 'normal',
size = 'm',
clickEvent,
children,
...props
}: IButtonProps) => {
const [isDisabled, setIsDisabled] = useState(false)
return (
<button
css={{
...BUTTON_SHAPE[shape],
...BUTTON_SIZE[size],
}}
disabled={isDisabled}
onClick={async () => {
setIsDisabled(true)
try {
await clickEvent()
} catch {
console.log('실패')
}
setIsDisabled(false)
}}
{...props}
>
{children}
</button>
)
}
export { Button }
위에서 정의한 Button Component를 아래와 같이 사용할 수 있다!
import { Button } from '../component/Button' // 정의한 component를 불러온다!
// test하기 위해서 아래와 같은 함수를 작성해서 넣어봤다!
const test = async () => {
const promise = await new Promise((resolve, reject) => {
setTimeout(() => resolve('완료!'), 4000)
})
console.log(promise)
}
// 하단과 같이 clickEvent에 클릭시 실행될 함수를 넣어준다!
<Button size="m" shape="normal" clickEvent={test}>
test
</Button>
'React' 카테고리의 다른 글
zustand useshallow는 언제쓸까? (2) | 2023.11.19 |
---|---|
useCallback를 사용하는 이유 (0) | 2023.11.19 |
useMemo를 사용하는 이유 (0) | 2023.11.19 |
React 렌더링 - 부모 컴포넌트와, 자식 컴포넌트 (0) | 2023.11.15 |
[React] React Form library Formik 학습 (0) | 2022.06.24 |