input lose focus on setState React - javascript

Whenever I am using setState my focus of input lost.
Where I am going wrong please tell me.
I am new to React.
This is my child component here I am using material-ui:-
const { onChangeEmail, onChangePassword, onPressSignIn, emailValue, passwordValue } = props;
<TextField
onChange={onChangeEmail}
value={emailValue}
variant="outlined"
id="email"
label="Enter your email"
name="email"
autoComplete="email"
/>
<TextField
onChange={onChangePassword}
value={passwordValue}
variant="outlined"
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
my Parent component:-
const [state, setState] = useState({
email: "",
password: "",
})
<SigninForm
onChangeEmail={(evt) => {
setState({
...state,
email : evt.target.value
})
}}
emailValue={state.email}
passwordValue={state.password}
onChangePassword={(evt) => {
setState({
...state,
password : evt.target.value
})
}}
/>
Thanks!!!

Your useState hook triggers render SigninForm each time you type as a result you loose focus. You can try onBlur to update state on focus out event and don't pass values to input

Related

How to combine useState and useEffect properly

I want to compare 2 inputs value. The typical password/repeat password input in a form.
Using onChange react useState render the DOM but not immediately because I shopuld use useEffect.
But I'm not sure how to combine both. I'm conscious there is other answers replying something similar but I can't apply to this case.
This is my useSstate:
const [user, setUser] = useState({
username: '',
password: '',
});
This is my onInputChange function:
const onInputChange = (e) => {
if ((e.target.id === 'password') === (e.target.id === 'confirmPassword')) {
console.log('Match!')
} else {
console.log('DO NOT Match')
}
setUser({ ...user, [e.target.name]: e.target.value });
console.log('User Updating values: ', user)
}
This is the input (MUI textfield):
<TextField
id="password"
name="password"
label="Password"
type="password"
onChange={(e) => onInputChange(e)}
/>
<TextField
id="confirmPassword"
name="confirmPassword"
label="Confirm password"
type="password"
onChange={(e) => onInputChange(e)}
/>
Could you help me with this, please?
Here you can find how it works
CodeSandBox
This is not best practice because you should match password on submit or on blur event trigger on each input.
Ask me if you need furthur help !
Thank You.

Yup and react hook form input validation bug

I have a problem in the input validation. The validation works when I submit and a error message appears, but when I press the first key on the keyboard nothing appears in the textarea and the error message disappears; after that, I can write normally. Its an inconvenience and I don't know why its happening. I am using the TextArea from Material UI. The code snippet of a login form is below.
const schema = yup.object().shape({
username: yup.string().matches(/^[a-z0-9]+$/, 'Must be all lower-case letters.').required(),
password: yup.string().required(),
})
const Login = props => {
const [formValues, setFormValues] = React.useState({
username: "",
password: ""
});
const { register,errors, handleSubmit } = useForm({
resolver: yupResolver(schema),
mode: 'onSubmit',
});
const onSubmit = async (data, e) => {
e.preventDefault()
const isValid = await schema.isValid(data)
if(isValid){
console.log(data);
}
}
return (
<Container component="main" maxWidth="xs">
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<TextField
autoFocus
required
fullWidth
id="username"
label="Username"
name="username"
value={formValues.username}
inputRef={register}
helperText = {errors.username?.message}
/>
<TextField
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
value={formValues.password}
inputRef={register}
helperText = {errors.password?.message}
/>
<Button
type="submit"
fullWidth
className={classes.submit}
>
Login
</Button>
</form>
</div>
</Container>
);
}
I worked around this (in React Native) by using reValidateMode:"onBlur" in the useForm() options.
This way it doesn't retry the validation until the user leaves the input.

Why event target not passing through multiple react functions?

So I am trying to make a textfield component in React that is highly reusable but whenever I try to access event.target.name or event.target.value I get empty data.
Is there any way to get this code to work?
function LoginForm() {
const [form, setValues] = useState({
username: "",
password: ""
});
const printValues = e => {
e.preventDefault();
console.log(form.username, form.password);
};
const updateField = e => {
setValues({
...form,
[e.target.name]: e.target.value
});
};
const TextField = props => {
return(
<label>
React Component:
<input
value={props.value}
name='react'
onChange={e => props.change(e)}
/>
</label>
)
}
return (
<form onSubmit={printValues}>
<TextField
value={form.username}
name='username'
change={updateField}
/>
<br />
<TextField
value={form.password}
name='password'
change={updateField}
/>
<br />
<button>Submit</button>
</form>
);
}
This code is an example that I have gotten to work. Why does this code work but not the code above?
function LoginForm() {
const [form, setValues] = useState({
username: "",
password: ""
});
const printValues = e => {
e.preventDefault();
console.log(form.username, form.password);
};
const updateField = e => {
setValues({
...form,
[e.target.name]: e.target.value
});
};
return (
<form onSubmit={printValues}>
<label>
Username:
<input
value={form.username}
name="username"
onChange={updateField}
/>
</label>
<br />
<label>
Password:
<input
value={form.password}
name="password"
type="password"
onChange={updateField}
/>
</label>
<br />
<button>Submit</button>
</form>
);
}
your child component has it's name prop hardcoded name='react' and that's because your [e.target.name]: e.targe.value statement is not working, use name={props.name} instead and it would solve the problem.
const TextField = props => {
return(
<label>
React Component:
<input
value={props.value}
name={props.name}
onChange={e => props.change(e)}
/>
</label>
)
}
The first code you show has a prop change instead of the onChange event listener in the TextField component.
I was looking here https://material-ui.com/es/components/text-fields/ because I never used material-ui, and in the example they still use the regular onChange.
So try changing change for onChange, as it is the only difference between both code examples besides the use of the component.

React onChange not updating state

I am creating a simple login form and I am saving the users information to state as they type. However, the value does not register to state as expected.
Here is the user state
const [user, setUser] = useState({
firstName: '',
lastName: '',
email: ''
});
Here is the input component
export function Input({ id, placeholder, autoComplete, type, name, label, value, handleInputChange }) {
return (
<div className="form-input">
<label className="form-label" htmlFor={id}>{label}</label>
<input
placeholder={placeholder}
autoComplete={autoComplete}
id={id}
type={type}
name={name}
value={value}
onChange={handleInputChange}
/>
</div>
)
}
Here is the handleInputChange function that is passed into the input component
function handleInputChange(event) {
const { name, value } = event.target;
setUser({ ...user, [name]: value });
}
Here is how one of the input components is used in the parent component
<Input
id="first-name"
placeholder="Charlie"
autoComplete="given-name"
type="text"
name="firstName"
label="First Name"
value={user.firstName}
handleInputChange={handleInputChange}
/>
Here are some resources I've looked at thus far:
https://reactjs.org/docs/hooks-reference.html#usestate
onChange not updating React
https://daveceddia.com/usestate-hook-examples/
I'd suggest to create one state per input field:
export function Form({ addItem }) {
const [name, setName] = useState('');
return (
<form>
<Input
id="first-name"
placeholder="Charlie"
autoComplete="given-name"
type="text"
name="firstName"
label="First Name"
value={user.firstName}
handleInputChange={(event) => setName(event.target.value)}
/>
</form>
);
}

HandleChange/setState stopped working after migrating to react useState hook

I had a component using classBased react, and it was working fine, I decided to switch to usestate and it stopepd working. Now the handlechange records the state in a random manner, but it doesnt work properly
My handlechange and the useState
const [state, setState] = useState({
email: "",
password: "",
wrongCombo: false,
serverError: false
})
const handleChange = (evt) => {
const target = evt.target;
const value = target.value;
const name = target.name;
console.log(name)
console.log(value)
setState({
[name]: value
});
}
My handlesubmit (it detects random values in that console.log, icant find the logic, but the log wont get both values as per inputed in the handlechange)
const handleSubmit = (event) => {
event.preventDefault();
const { email, password } = state;
console.log(state)
props.login(email, password, "login").
then(data => {
}).catch((err) => {
if (err == "Error: Request failed with status code 403") {
setState({
wrongCombo: true
}, () => {
})
} else if (err == "Network error") {
setState({
serverError: true
})
}
})
}
And this is my render
<div>
<form>
{state.wrongCombo ? <Alert variant="danger" dismissible onClose={handleDismiss}> Wrong email and password combination </Alert> : null}
{state.serverError ? <Alert variant="danger" dismissible onClose={handleDismiss}> Server Error </Alert> : null}
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" name="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email" onChange={handleChange} />
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" name="password" class="form-control" id="exampleInputPassword1" placeholder="Password" onChange={handleChange} />
</div>
<div className="text-center buttonContainer">
<button type="submit" class="btn btn-primary buttonLogin" onClick={handleSubmit}>Submit</button>
</div>
</form>
</div>
From the docs on useState:
unlike this.setState in a class, updating a state variable always replaces it instead of merging it.
You must replace all values in a useState object when updating them. You are only providing an object to the updater with one of the keys, so only that key will be retained.
A simple pattern for doing this would be to spread the previous state before passing your update:
setState(prev => ({...prev, [newKey]: newVal }));

Categories