'once deleting out of input, focus previous input react
I am having issues trying to focus on a previous input once I delete out of the input that I am in. I have 6 inputs, all with a maxLength of 1. When I press the backspace key I would like to delete the value and move to the previous input. I have tried a variety of things but nothing seems to work how I need.
Here is my code
This is the Auth component which is passing props to verify (the page with the inputs)
const Auth = ({ sub }) => {
let params = useParams();
const navigate = useNavigate();
const [rec, setRec] = useState({
accept: false,
email: '',
phone: '',
pin: ['', '', '', '', '', '']
})
const onPaste = (event) => {
event.preventDefault()
const pasted = event.clipboardData.getData("text/plain")
setRec({ ...rec, pin: pasted.split("").slice(0, rec.pin.length) })
// target event last sibling
event.target.parentNode.lastChild.focus()
}
function update(event, index) {
event.preventDefault()
setRec({
...rec, pin: [
...rec.pin.slice(0, index),
event.target.value,
...rec.pin.slice(index + 1)
]
})
}
const handleFocus = (event) => {
if (event.target.nextSibling)
event.target.nextSibling.focus();
// if value is deleted, focus previous sibling
// if all siblings are empty, focus first sibling
if (event.target.value === '' && event.target.previousSibling === null)
event.target.parentNode.firstChild.focus()
}
const onKeyPress = (event) => {
// if backspace is clicked, go to previous input
if (event.key === 'Backspace' && event.target.value === '') {
event.target.previousSibling.focus()
}
}
const handleChange = (name, value) => {
if (name === 'mobile') name = 'phone'
const recState = {
...rec,
[name]: value,
}
setRec(recState)
}
const toggleAccept = () => {
if (!rec.accept) {
setRec({
...rec,
accept: true
});
} else {
setRec({
...rec,
accept: false
});
}
}
const handleSubmit = async () => {
const { accept, email, phone } = rec
if (params.method === 'email' && !email) return app.actions.setError('Enter an email')
else if (params.method !== 'email' && !phone) return app.actions.setError('Enter a phone number')
const send = params.method === 'email' ? { email } : { phone }
if (!accept) return app.actions.setError('Please accept the terms & conditions')
try {
await app.actions.setLoading(true)
// if there is already a user, just login, else create user first
await user.actions.login(send)
await app.actions.setLoading(false)
navigate(`/auth/verify/login/${params.method || 'phone'}`)
} catch (e) {
if (e.response && e.response.status === 404) {
// try join
await user.actions.join(send)
await app.actions.setLoading(false)
return navigate(`/auth/verify/join/${params.method || 'phone'}`)
}
await app.actions.setLoading(false)
await app.actions.setError(e)
}
}
const handleVerify = async ({ context, method }) => {
const { email, phone, pin } = rec
const joinPin = pin.join('');
if (method === 'email' && !email) return app.actions.setError('Enter an email')
else if (method !== 'email' && !phone) return app.actions.setError('Enter a phone number')
const send = method === 'email' ? { email } : { phone }
await app.actions.setError(null)
try {
await app.actions.setLoading(true)
if (context === 'login') {
await user.actions.loginVerify({
...send,
pin: joinPin,
})
} else {
await user.actions.verify({
...send,
pin: joinPin,
})
}
await app.actions.init()
await app.actions.setLoading(false)
navigate('/')
} catch (e) {
await app.actions.setLoading(false)
await app.actions.setError(e)
}
}
return (
<>
{sub ?
<Verify
context={params.context}
handleChange={handleChange}
handleFocus={handleFocus}
handleSubmit={() => handleVerify({ context: params.context, method: params.method })}
onKeyPress={onKeyPress}
method={params.method}
paste={onPaste}
update={update}
rec={rec} />
:
<Jogin
handleChange={handleChange}
handleSubmit={handleSubmit}
method={params.method}
toggleAccept={toggleAccept}
rec={rec} />
}
</>
)
}
export default Auth
and here is the verify component
import React from 'react'
import { onFormSubmit } from '../../utility/form'
import { Navigate, useNavigate } from 'react-router-dom'
import user from '../../model/user'
import app from '../../model/app'
const Verify = ({ handleSubmit, method, rec, paste, update, handleFocus, onKeyPress }) => {
const navigate = useNavigate();
const { email, phone } = rec
const send = method === 'email' ? { email: email } : { phone: phone }
const resendPin = async () => {
try {
await app.actions.setLoading(true)
// if there is already a user, just login, else create user first
await user.actions.login(send)
await app.actions.setLoading(false)
navigate(`/auth/verify/login/${method || 'phone'}`)
} catch (e) {
if (e.response && e.response.status === 404) {
// try join
await user.actions.join(send)
await app.actions.setLoading(false)
return navigate(`/auth/verify/join/${method || 'phone'}`)
}
await app.actions.setLoading(false)
await app.actions.setError(e)
}
}
const renderContent = () => {
const methodLabel = method === 'email' ? 'email address' : 'phone number'
return (
<>
<div id="back-grad" />
<div className="col-md-8">
<div className='verify-text-section'>
<p className="verify-text pb-5">
Enter the PIN number we just sent to your {methodLabel}.
</p>
</div>
<div className="flex">
{rec.pin.map((s, key) => (
<input key={key} className='code-input mr-2' value={s} maxLength='1' onPaste={(e) => paste(e)} onKeyDown={e => onKeyPress(e)} onInput={(e) => update(e, key)} onChange={(e) => handleFocus(e)} inputMode='numeric' autoFocus={key === 0} />
))}
</div>
<div className="verify-resend mt-3" onClick={resendPin}>Resend Code</div>
<div className="flex margin-set text-center">
<button className="btn btn-block text-white verify-btn">
<p className="verify-btn-text">VERIFY</p>
</button>
</div>
</div>
</>
)
}
return (
<>
{rec.email.length < 1 && rec.phone.length < 1 ? <Navigate to={'/auth'} />
:
<div className="d-flex align-items-center h-full">
<form className="container" onSubmit={e => onFormSubmit(e, handleSubmit)}>
<div className="row justify-content-center">
{renderContent()}
</div>
</form>
</div>
}
</>
)
}
export default Verify
any help is appreciated!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
