I'm making validation of an email input in my React App, but I want that input should have both # and .(dot) while submitting the form. I tried the .some() method but if only one condition is true then it will return true but I want both:
const emailValidation = ["#", "."];
<input
type="text"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
onBlur={(e) => {
setIsEmailValid(
emailValidation.some((el) => e.target.value.includes(el))
);
}}
/>
<input
type="text"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
onBlur={(e) => {
setIsEmailValid(
emailValidation.every((el) => e.target.value.includes(el))); }}
/>
Here you just need to use every() method instead of some()
Related
Why can't I put a value in the input? The problem is: I need to put a 'name' in <Form.Item> to apply the rules. Without that, the rules will not be able to work, but if you remove the name="userName" from <Form.Item the value appears at the input.
How can i solve that?
<Form autoComplete="off" layout="vertical" onFinish={handleFinish}>
<Form.Item name="userName" rules={getTextRule('name')}>
<Input value={fields?.firstName} name="firstName" onChange={(e) => {
handleInputChange(e)
}} />
</Form.Item>
</Form.Item>
simple we can code like
const [text,setText] = useState('')
return(
<input type='text' value={text} onChange={e=>setText(e.target.value)}/>
)
If you use the form you can let Ant Form manage the state by removing the value & the onChange props on the <Input />.
Else if you manage the state by yourself make sure to get the value from the e.target.value.
ex:
const [fields, setFields] = useState({})
const handleOnChange = (e) => {
setFields((state) => {
...state,
[e.target.name]: e.target.value,
})
}
return (
<Input
name="firstName"
value={fields.firstName}
onChange={handleOnChange}
/>
)
i want to get the values from 5 input fields and save them inside a single state of arrays , how can i achieve that ?
const [features,setFeatures] = useState([]);
const handleChange = e => {
setFeatures(prev => ({ ...prev, features, [e.target.name]: e.target.value }))
}
<Input type="text" name="features" label="Feature 1" value={features} required change={handleChange} />
<Input type="text" name="features" label="Feature 2" value={features} required change={handleChange} />
<Input type="text" name="features" label="Feature 3" value={features} required change={handleChange} />
<Input type="text" name="features" label="Feature 4" value={features} required change={handleChange} />
<Input type="text" name="features" label="Feature 5" value={features} required change={handleChange} />
You can check the below implementation
Note that I hardcoded the array length and I'd assume your input array is static. If your input array is dynamic, you can use iteration for generating input fields. Besides that, I modified Input to input and change to onChange for the primitive input element. The button and form are for demo only.
const App = () => {
const [features,setFeatures] = React.useState(new Array(5));
const handleChange = (e,index) => {
const updatedFeatures = [...features] //clone data
updatedFeatures[index] = e.target.value
setFeatures(updatedFeatures)
}
const handleSubmit = (e) => {
e.preventDefault();
console.log(features);
}
return (<form onSubmit={handleSubmit}><input type="text" name="features" label="Feature 1" value={features[0]} required onChange={(e) => handleChange(e, 0)} />
<input type="text" name="features" label="Feature 2" value={features[1]} required onChange={(e) => handleChange(e, 1)} />
<input type="text" name="features" label="Feature 3" value={features[2]} required onChange={(e) => handleChange(e, 2)} />
<input type="text" name="features" label="Feature 4" value={features[3]} required onChange={(e) => handleChange(e, 3)} />
<input type="text" name="features" label="Feature 5" value={features[4]} required onChange={(e) => handleChange(e, 4)} />
<button type="submit">Submit</button>
</form>)
}
ReactDOM.render(
<App/>,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
<form
className="login"
onSubmit={e => {
alert('hey getting called')
e.preventDefault()
this.authorizeUser(e)
}}
>
<input
type="text"
name="email"
onChange={e => this.handleInputChange(e)}
value={email}
className="login-input"
placeholder="Email Adress"
autoFocus
/>
<input
type="password"
name="password"
onChange={e => this.handleInputChange(e)}
value={password}
className="login-input"
placeholder="Password"
/>
<button
type="submit"
style={{height: '37px', float: 'left'}}
className="login-button"
>
Login
</button>
</form>
code is not reaching up to alert statement.
instead i see url changes to ->
http://localhost:3000/signin?email=testUSer%40abx.in&password=1234567 and page gets refreshed
This issue is happening after i updated react version from 16.9 to 17.0.0.
UPDATE
When i add the listener via add event listener inside componentDidMount() then suddenly it started working as expected!
still wonder why the onSubmit directly on form didn't work
//The value coming from the input that triggered the event is getting updated in the state but not displaying in the browser, I don't really understand what's happening, I have been using the same method to update the state in my other project
import React, { useState } from "react";
const Register=()=>{
const [user,setUser]=useState({
name:"",
email:"",
password:"",
reenterPassword:""
});
let changeHandler=(e)=>{
const { name, value } = e.target
setUser({
...user,
[name]: value
})
}
return(
<div className="register">
<h1>Register</h1>
<input onChange={changeHandler} name="Username" placeholder="Please Enter Your Name" type="text" defaultValue="" value={user.name}/>
<input onChange={changeHandler} name="Email" placeholder="Enter your Email" type="email" value={user.email}/>
<input onChange={changeHandler} name="Password" placeholder="Create Your Password" type="password" value={user.password}/>
<input onChange={changeHandler} name="ReEnterPassword" placeholder="Re-Enter Your Password" type="password" value={user.reenterPassword}/>
<div className="button">Register</div>
<div>OR</div>
<div className="button">Login</div>
</div>
)
}
export default Register;
[1]: https://i.stack.imgur.com/G8beV.png
there is good answer here about it: https://stackoverflow.com/a/58877875/2091359
you should not use useState like this, you can do useState for each input separately like this:
const [name, setName] = useState('')
const handleChangeName = (e) => {
setName(e.target.value);
}
return(
<div className="register">
<h1>Register</h1>
<input onChange={handleChangeName} name="Username" placeholder="Please Enter Your Name" type="text" value={name}/>
...
or use useReduce
Try this code:
const Register=()=>{
const [user,setUser]=useState({
Username:"",
Email:"",
Password:"",
ReEnterPassword:""
});
let changeHandler=(e)=>{
const { name, value } = e.target
setUser({
...user,
[name]: value
})
}
return (
<div className="register">
<h1>Register</h1>
<input onChange={(e)=>changeHandler(e)} name="Username" placeholder="Please Enter Your Name" type="text" defaultValue="" value={user.name}/>
<input onChange={(e)=>changeHandler(e)} name="Email" placeholder="Enter your Email" type="email" value={user.email}/>
<input onChange={(e)=>changeHandler(e)} name="Password" placeholder="Create Your Password" type="password" value={user.password}/>
<input onChange={(e)=>changeHandler(e)} name="ReEnterPassword" placeholder="Re-Enter Your Password" type="password" value={user.reenterPassword}/>
<div className="button">Register</div>
<div>OR</div>
<div className="button">Login</div>
</div>
);
}
export default Register;
You need to use the same name for the html input attribute too, and try to use callback in the onChange event.
So if I'm using on input I can toggle password visibility.
I'm having trouble with it only toggling one input at a time.
D
Currently my code looks like this..
const [isPasswordShown, setPasswordShown] = useState(false);
const togglePassword = () => {
setPasswordShown(isPasswordShown ? false : true);
};
const renderTogglePasswordIcon = () => {
return (
<FontAwesomeIcon
onClick={togglePassword}
icon={isPasswordShown ? faEye : faEyeSlash}
/>
);
};
<Input
variant={InputVariants.text}
type={isPasswordShown ? "text" : "password"}
name="password"
label="Password"
error={errors.password?.message}
onChange={(e) => handlePasswordInput(e)}
ref={register}
/>
<i>{renderTogglePasswordIcon()}</i>
<Input
variant={InputVariants.text}
type={isPasswordShown ? "text" : "password"}
name="passwordConfirmation"
label="Confirm Password"
error={errors.passwordConfirmation?.message}
ref={register}
onChange={(e) => confirmPassword(e)}
/>
<i>{renderTogglePasswordIcon()}</i>
Do you want to toggle the inputs separately or only one of the inputs?
I would only use the toggle function for one input element. So you can set the html type to password hardcoded in the second element:
<Input
variant={InputVariants.text}
type={isPasswordShown ? "text" : "password"}
name="password"
label="Password"
error={errors.password?.message}
onChange={(e) => handlePasswordInput(e)}
ref={register}
/>
<i>{renderTogglePasswordIcon()}</i>
<Input
variant={InputVariants.text}
type="password"
name="passwordConfirmation"
label="Confirm Password"
error={errors.passwordConfirmation?.message}
ref={register}
onChange={(e) => confirmPassword(e)}
/>
<i>{renderTogglePasswordIcon()}</i>
Otherwise you can use a second parameter