Reputation: 1677
I've only now noticed this but for some reason I can't seem to type into some input fields in my page built with React and NextJS. This only happens on mobile, on Desktop the forms works perfectly.
Here's what's weird however. I can type passwords in just fine, this only happens on other input types (such as type="text"
and type="email"
).
Things can be still typed into the text box with keyboard predictions, but not with the normal keyboard.
Here's my form:
function LoginForm(props) {
return (
<form onSubmit={props.submitLogin} className={"flex flex-col self-center justify-between w-full"}>
<div className={"text-xl text-center mb-4"}>Sign In</div>
<div className={"text-gray-600 text-xs pl-2"}>Username:</div>
<input
value={props.formData.username}
name="username"
type="text"
onChange={props.updateField}
className={"form__username my-1 p-2 rounded border-gray-300 border border-solid"}
/>
<div className={"text-gray-600 text-xs pl-2"}>Password:</div>
<input
value={props.formData.password}
name="password"
type="password"
onChange={props.updateField}
className={"form__password my-1 p-2 rounded border-gray-300 border border-solid"}
/>
<button
className={"bg-blue-500 hover:bg-blue-400 focus:bg-blue-600 focus:shadow-outline p-2 mt-4 rounded border-blue-500 uppercase font-semibold text-gray-100 border border-solid"}
>Login</button>
<div className={"p-2 text-center"} dangerouslySetInnerHTML={createMarkup(props.formMessage)}>
</div>
</form>
)
}
The containing Component:
export function LoginModal(p) {
const [showLogin, toggleLogin] = useState(p.showLogin)
useEffect(() => {
toggleLogin(p.showLogin);
}, [p]);
const sendSignupForm = e => {
e.preventDefault();
if ( Object.values(form).some(empty) ) {
props.setMessage("Please fill all the fields.")
} else {
props.setSignupData(form)
}
};
const [form, setValues] = useState({
username: '',
password: '',
checked: false,
email: ''
});
const [message, setMessage] = useState('')
const updateField = e => {
setValues({
...form,
[e.target.name]: e.target.type === 'checkbox' ? e.target.checked : e.target.value
});
};
const spring = useSpring({
from: { opacity: 0 },
to: { opacity: !p.state ? 1 : 0 }
});
const transitions = useTransition(!p.state, null, {
from: { transform: `scale(1.5)`, opacity: 0 },
enter: { transform: `scale(1)`, opacity: 1 },
leave: { transform: `scale(1.5)`, opacity: 0 },
unique: true
});
const submitLogin = async(e) => {
e.preventDefault();
await
login(form).then(data => {
if(data.message) {
setMessage(data.message)
} else{
p.setData(data.user)
}
})
}
const submitSignup = async(e) => {
e.preventDefault();
if(form.checked){
await
register(form).then(data => {
console.log(data)
if(data.message) {
setMessage(data.message)
console.log(message)
} else{
p.setData(data.user)
}
})
} else {
setMessage("Please accept our privacy policy.")
}
}
return (
<Fragment>
<animated.div style={spring} />
{transitions.map(({ item, key, props }) =>
item ? (
<div key={key} className={"z-10 flex absolute w-screen h-screen top-0 left-0"}>
<animated.div
className={`popup md:max-w-4xl md:h-2/4 xs:w-full justify-center flex lg:flex-row xs:flex-col fixed rounded left-0 right-0 mx-auto self-center -mt-3 sm:mt-0`}
style={ props }
>
<button className={"absolute right-0 p-4 xs:top-0"} onClick={() => p.onClick(false)}><Close/></button>
<div className={"hidden bg-gray-900 rounded rounded-r-none w-2/4 lg:flex items-center justify-center "}>
<div className="text-gray-100 header__logo--white self-centertext-6xl xs:mx-auto sm:mx-0">
<Logo/>
</div>
</div>
<div className={"popup__forms flex flex-col xs:mx-auto xs:w-full justify-center popup__form rounded rounded-l-none lg:w-2/4 p-5"}>
{ showLogin ? (
<LoginForm submitLogin={submitLogin} updateField={updateField} formMessage={message} formData={form}/>
) : (
<SignUpForm submitSignup={submitSignup} updateField={updateField} formMessage={message} formData={form}/>
)
}
{ showLogin ? (
<div className="my-4 text-center">Not a member? <a onClick={() => toggleLogin(false)} className={"cursor-pointer text-blue-500 hover:text-blue-400 underline"}>Sign Up</a></div>
) : (
<div className="my-4 text-center">Already a member? <a onClick={() => toggleLogin(true)} className={"cursor-pointer text-blue-500 hover:text-blue-400 underline"}>Login</a></div>
)
}
</div>
</animated.div>
<animated.div
className={`popup-background fixed top-0 left-0 w-full items-center justify-center h-screen`}
onClick={() => p.toggle(!p.state)}
style={props}>
</animated.div>
</div>
) : null
)
}
</Fragment>
)
}
All of these are updated by the same function:
const updateField = e => {
setValues({
...form,
[e.target.name]: e.target.type === 'checkbox' ? e.target.checked : e.target.value
});
};
const [form, setValues] = useState({
username: '',
password: '',
email: ''
});
Live example, click on "sign up" or "login" and try to input values.
I'm pretty lost, what's causing this?
I've looked at this, this and this but they don't seem to have anything to do with my problem.
Upvotes: 0
Views: 2547
Reputation: 49
I faced this issue due to the parent component of my input
being rerendered endlessly. It was caused by an infinite hook loop. i.e.
const [count, setCount] = useState(0);
// This useEffect loops forever, constantly resetting the value of the input
useEffect(() => {
...
setCount(0);
...
}, [count]);
return (
...
<input
value={count}
onChange={(e) => setCount(e.target.value)}
/>
...
);
Make sure your parent component isn't rerendering endlessly, otherwise your input
will rerender endlessly as well, which can cause it to continuously reset its value.
Upvotes: 0
Reputation: 1677
This happened because one of my inputs had this CSS rule:
.form__username {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
Once I removed it it started working properly.
Upvotes: 5