I'm attempting to implement a long press button functionality in React where pressing and holding the '0' digit button for 3 seconds turns it into a '+' symbol, and when it's just clicked, it should print '0'. The desired behavior is similar to the dialpad in our phones. However, in my implementation, when I long press the '0' digit button, it does print '+', but it also prints two '0's along with it. How can I resolve this issue?
Here is my code:
interface PhoneDialPadPopoverProps {
isLoading: boolean;
onConnect: (digits: string) => void;
}
const PhoneDialPadPopover = ({
isLoading,
onConnect,
}: PhoneDialPadPopoverProps) => {
// State variables
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
const [enteredDigits, setEnteredDigits] = useState('');
const [isLongPressing0, setIsLongPressing0] = useState(false); // Flag to track long press
const [longPressTimer, setLongPressTimer] = useState<NodeJS.Timeout | null>(
null
);
const theme = useTheme();
const mdUp = useMediaQuery((theme: Theme) => theme.breakpoints.up('md'));
const open = Boolean(anchorEl);
const id = open ? 'connect-dial-pad-popover' : undefined;
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const handleButtonClick = (digit: string) => {
const newDigits = enteredDigits + digit;
setEnteredDigits(newDigits);
onConnect(digit);
};
const handleLongPress = () => {
setLongPressTimer(null); // Clear existing timer
handleButtonClick('+'); // Trigger '+' button action
};
const handleMouseDown = () => {
// Start the timer for long press
const timer = setTimeout(handleLongPress, 3000); // Adjust the delay as needed
setLongPressTimer(timer);
};
const handleMouseUp = () => {
// Clear the timer for long press
if (longPressTimer) {
clearTimeout(longPressTimer);
setLongPressTimer(null);
}
// If it was a long press, prevent the regular click event
if (isLongPressing0) {
setIsLongPressing0(false);
} else {
// Regular click event for '0' digit only if it's not a long press
if (!isLongPressing0) {
handleButtonClick('0');
}
}
};
const dialerButtons = [
{ digit: '1' },
{ digit: '2', letters: 'ABC' },
{ digit: '3', letters: 'DEF' },
{ digit: '4', letters: 'GHI' },
{ digit: '5', letters: 'JKL' },
{ digit: '6', letters: 'MNO' },
{ digit: '7', letters: 'PQRS' },
{ digit: '8', letters: 'TUV' },
{ digit: '9', letters: 'WXYZ' },
{ digit: '*' },
{ digit: '0', letters: '+' },
{ digit: '#' },
];
return (
<div>
<Button
aria-describedby={id}
variant={'outlined-icon'}
color="grey"
onClick={handleClick}
startIcon={
isLoading ? (
<CircularProgress size={16} />
) : (
<Iconify icon="mdi:dialpad" />
)
}
></Button>
<StyledPopover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: 'top',
horizontal: 'left',
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
marginThreshold={mdUp ? 64 : 32}
>
<IconButton
aria-label="close"
onClick={handleClose}
color="grey"
sx={{
position: 'absolute',
top: theme.spacing(1),
right: theme.spacing(2),
}}
>
<Iconify icon="mdi:close" />
</IconButton>
<TextField
variant="outlined"
fullWidth
value={enteredDigits}
InputProps={{
readOnly: true,
inputProps: {
style: { textAlign: 'center', fontWeight: 'bold' },
'aria-readonly': true,
},
}}
style={{ marginTop: '25px' }}
/>
<Box display="grid" gridTemplateColumns="repeat(3, 1fr)" gap={1}>
{dialerButtons.map((button, index) => (
<button
key={index}
onMouseDown={() =>
button.digit === '0' ? handleMouseDown() : null
}
onMouseUp={handleMouseUp}
onClick={() => handleButtonClick(button.digit)}
style={{
border: 'none',
background: 'none',
outline: 'none',
padding: theme.spacing(1),
}}
>
<Typography variant="body2" align="center" fontWeight="bold">
{button.digit}
</Typography>
{button.letters && (
<Typography variant="body2" align="center" color="grey">
{button.letters}
</Typography>
)}
</button>
))}
</Box>
</StyledPopover>
</div>
);
};
export default PhoneDialPadPopover;
"I attempted to implement a long press functionality for the '0' digit button in a React component. I expected that when I long pressed the '0' button, it would print a '+' symbol, and when I single-clicked it, it would print '0'. However, when I long pressed the button, it printed '+00' instead of just '+'. I tried adjusting the code logic and timer delay, but it still resulted in the same issue."