useDoubleCheck
might be my favorite frontend hack
function callAll<Args extends Array<unknown>>(
...fns: Array<((...args: Args) => unknown) | undefined>
) {
return (...args: Args) => fns.forEach((fn) => fn?.(...args))
}
/**
* Use this hook with a button and it will make it so the first click sets a
* `doubleCheck` state to true, and the second click will actually trigger the
* `onClick` handler. This allows you to have a button that can be like a
* "are you sure?" experience for the user before doing destructive operations.
*/
export function useDoubleCheck() {
const [doubleCheck, setDoubleCheck] = useState(false)
function getButtonProps(
props?: React.ButtonHTMLAttributes<HTMLButtonElement>,
) {
const onBlur: React.ButtonHTMLAttributes<HTMLButtonElement>['onBlur'] =
() => setDoubleCheck(false)
const onClick: React.ButtonHTMLAttributes<HTMLButtonElement>['onClick'] =
doubleCheck
? undefined
: (e) => {
e.preventDefault()
setDoubleCheck(true)
}
const onKeyUp: React.ButtonHTMLAttributes<HTMLButtonElement>['onKeyUp'] = (
e,
) => {
if (e.key === 'Escape') {
setDoubleCheck(false)
}
}
return {
...props,
onBlur: callAll(onBlur, props?.onBlur),
onClick: callAll(onClick, props?.onClick),
onKeyUp: callAll(onKeyUp, props?.onKeyUp),
}
}
return { doubleCheck, getButtonProps }
}
Cribbed from Kent C Dodds a couple years back. Its a great "confirmation" required behavior thats way better than an annoying confirmation dialog.