How to pass the value of checkbox in react? - reactjs

God Day, I'm trying to pass a Boolean value of the checkbox using onChange but onChange is already use to toggle the checkbox value. I dont have idea on what will be the other way around. Please guide me Thank you much.
function ExperienceForm() {
const [postData, setPostData] = useState({intern: ''});
const dispatch = useDispatch();
const handleSubmit = (e) => {
e.preventDefault();
dispatch(createPost(postData))
}
const [state, setState] = React.useState({
intern: false,
});
const handleChange = (event) => {
setState({ ...state, [event.target.name]: event.target.checked });
console.log(state.intern);
};
return (
<form autoComplete="off" noValidate className="form" onSubmit={handleSubmit}>
<FormControlLabel control={
<Checkbox
checked={state.intern}
onChange={handleChange ((e) => setPostData({ ...postData, intern: e.target.value }))}
name="intern"
color="primary"
value={state.intern}
/>
}
label="Intern"
/><br/>
<Button className="button" variant="container" color="primary" size="large" type="submit" block>Submit</Button>
</form>
);
}
export default ExperienceForm;

I don't see code of your <FormControlLabel /> and <Checkbox /> components, but with regular html input you can do it like this:
import React, { useState } from "react";
function ExperienceForm() {
const [postData, setPostData] = useState({ intern: false });
const [state, setState] = useState({ intern: false });
const handleChange = ({ target }) => {
setState({ ...state, [target.name]: target.checked });
setPostData({ ...postData, intern: target.checked });
};
return (
<form autoComplete="off" noValidate className="form">
<h2>postData.intern: {postData.intern.toString()}</h2>
<h2>state.intern: {state.intern.toString()}</h2>
<input
type="checkbox"
checked={state.intern}
onChange={handleChange}
name="intern"
color="primary"
value={state.intern}
/>
<button type="submit">Submit</button>
</form>
);
}
export default ExperienceForm;

Related

i have problem with writing Page in react js?

I can't type in the fields for a page Login on React js and mdbootstrap and css
this is the problem please my developper Help me solve this problem I have suffered with it a lot What is the solution please help me with this problem
What is the root of this problem please fix my code
This is the problem code
import React, { useState } from 'react';
export default function App() {
const [iconsActive, setIconsActive] = useState('pill1');
const handleIconsClick = (value: string) => {
if (value === iconsActive) {
return;
}
setIconsActive(value);
};
const [values, setValues] = useState({
email: '',
password: '',
});
const [submitted, setSubmitted] = useState(false);
const [showSuccess, setShowSuccess] = useState(false);
const handleInputChange = (event) => {
event.persist();
setValues((values) => ({
...values,
[event.target.email]: event.target.value,
}));
};
const isFormValid = () => {
if (!values.email || !values.password) {
return false;
} else {
return true;
}
};
const handleSubmit = (e) => {
e.preventDefault();
setSubmitted(true);
if (isFormValid()) {
setShowSuccess(true);
}
};
return (
<div
className='text-center'
id='formm'
class='register-form'
onSubmit={handleSubmit}
>
{showSuccess && (
<div class='success-message'>Success! Thank you for registering</div>
)}
<MDBTabs pills justify className='mb-3'>
<MDBCol>
<MDBTabsItem>
<MDBTabsLink
onClick={() => handleIconsClick('pill1')}
active={iconsActive === 'pill1'}
>
<MDBIcon className='me-2' />
Login
</MDBTabsLink>
</MDBTabsItem>
</MDBCol>
<MDBTabsItem>
<MDBTabsLink
onClick={() => handleIconsClick('pill2')}
active={iconsActive === 'pill2'}
>
<MDBIcon className='me-2' />
Register
</MDBTabsLink>
</MDBTabsItem>
</MDBTabs>
<MDBTabsContent>
<MDBTabsPane show={iconsActive === 'pill1'}>
<MDBInput
className='mb-4'
type='email'
id='form7Example1'
label='Email address'
disabled={showSuccess}
value={values.email}
onChange={handleInputChange}
/>
{submitted && !values.email && (
<span id='email-error'>Please enter a email</span>
)}
<MDBInput
className='mb-4'
type='password'
id='form7Example2'
label='Password'
disabled={showSuccess}
value={values.password}
onChange={handleInputChange}
/>
{submitted && !values.password && (
<span id='password-error'>Please enter a last name</span>
)}
<MDBBtn type='submit' className='mb-4' block disabled={showSuccess}>
Sign in
</MDBBtn>
Your problem is here:
setValues((values) => ({
...values,
[event.target.email]: event.target.value,
}));
You are setting value to the wrong keys.
I would suggest you to create two states and separate handlers for every input OR you can do the following:
const handleInputChange = (type) => ({target}) => {
setValues((values) => ({
...values,
[type]: target.value,
}));
};
<MDBInput
value={values.email}
onChange={handleInputChange("email")}
/>
<MDBInput
value={values.password}
onChange={handleInputChange("password")}
/>

How to validate email and password using react hooks?

I am getting state values while clicking submit button but I am unable to do the validation for my login form and how to display the error messages below the input field when I enter my input wrong or empty. please give me a solution to this.Thanks in advance.
const Login = () => {
const [state, setState] = useState({
email: "",
password: ""
});
const handleChange = (e) => {
const {id, value} = e.target
setState(prevState => ({
...prevState,
[id]: value
}))
}
const handleSubmitClick = (e) => {
e.preventDefault();
console.log("Authenticated",state);
}
return(
<>
<div className="container">
<div className="title">
<form onSubmit={handleSubmitClick}>
<div className="form-group">
<input
type="email"
className="email"
placeholder="Email"
value={state.email}
onChange={handleChange}/>
</div>
<div className="form-group">
<input
type="password"
className="password"
placeholder="Password"
value={state.password}
onChange={handleChange}/>
</div>
<button type="submit" className="button">Enter</button>
</form>
</div>
</div>
</>
)
}
export default Login;
If you want to perform client-side validation, you can create hook like this:
const useEmailValidation = (email) => {
const isEmailValid = /#/.test(email); // use any validator you want
return isEmailValid;
};
And then you can use this hook in your form component:
...
const isEmailValid = useEmailValidation(state.email);
const isPasswordValid = usePasswordValidation(state.password);
const isFormValid = isEmailValid && isPasswordValid;
return (
...
<input
className={classNames({ 'invalid': !isEmailValid })}
type="email"
value={state.email}
onChange={handleChange}
/>
{!isEmailValid && 'Some error message'}
<button type="submit" disabled={!isFormValid} className="button">Enter</button>
...
);
...
Your validator hook can return validation message instead of boolean, like:
const useEmailValidation = (email) => {
if (!email || email.length === 0) {
return 'Email cannot be empty';
}
const isEmailValid = /#/.test(email); // use any validator you want
if (!isEmailValid) {
return 'Invalid email provided';
}
return null;
};
Also it is a good practice to show validation message only after field was focused before and after user tried to submit the form.
Formik is a great plugin that will help you perform form validation. The examples are also quite clear.
Or you could do something like this:
const Login = () => {
const [error, setError] = useState(null);
const [state, setState] = useState({
email: '',
password: '',
});
const validateEmail = (email) => {
const re =
/^(([^<>()[\]\\.,;:\s#"]+(\.[^<>()[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase());
};
const handleChange = (e) => {
const { id, value } = e.target;
setState((prevState) => ({
...prevState,
[id]: value,
}));
};
const handleSubmitClick = (e) => {
e.preventDefault();
if (!validateEmail(state.email)) {
setError('Invalid Email');
}
if (state.password.length < 8) {
setError('Password must be at least 8 chars long');
}
if (!error) {
// No errors.
}
};
return (
<>
<div className='container'>
<div className='title'>
{error && <div style={{ color: 'red' }}>{error}</div>}
<form onSubmit={handleSubmitClick}>
<div className='form-group'>
<input
type='email'
className='email'
placeholder='Email'
value={state.email}
onChange={handleChange}
/>
</div>
<div className='form-group'>
<input
type='password'
className='password'
placeholder='Password'
value={state.password}
onChange={handleChange}
/>
</div>
<button type='submit' className='button'>
Enter
</button>
</form>
</div>
</div>
</>
);
};
export default Login;
For an empty validation you can check it preventing the submit if the field is empty, like
const handleSubmitClick = (e) => {
e.preventDefault();
if(email.trim() === '' || password.trim() === ''){
//Add a h1 or section with the error message
}else{
console.log("Authenticated",state);
}
}
As long as the email field type is equal to email, which is your case, the browser should give an alert if the string is not an email. ("user#example.com")

How can I show the updated state?

When I'll click submit, it will save in the firestore, however, I still need to reload the page to update the state. How can I code it in a way that once I'll click submit, it will immediately reflect on the screen without reloading it?
const Account = () => {
const [displayName, setdisplayName] = useState(currentUser.displayName);
const [address, setAddress] = useState(currentUser.address);
const handleSubmit = async (event) => {
event.preventDefault();
try {
const userRef = firestore.collection("users").doc(currentUser.id);
const res = userRef.set(
{
displayName,
address,
},
{ merge: true }
);
} catch (err) {
console.log(err);
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<TextField
placeholder={currentUser.displayName}
value={displayName}
color="secondary"
required
onChange={(e) => setdisplayName(e.target.value)}
/>
<TextField
type="text"
placeholder={currentUser.address}
value={address}
onChange={(e) => setAddress(e.target.value)}
required
/>
<Button type="submit">Submit</Button>
</form>
</div>
);
};
export default MyAccount;
You can use 1 flag to mark when it submit,use useState update value of flag and page will change.
const Account = () => {
const [displayName, setdisplayName] = useState(currentUser.displayName);
const [address, setAddress] = useState(currentUser.address);
const [flag,setFlag] = useState(false);
const handleSubmit = async (event) => {
event.preventDefault();
try {
const userRef = firestore.collection("users").doc(currentUser.id);
const res = userRef.set(
{
displayName,
address,
},
{ merge: true }
);
setFlag(true);
} catch (err) {
console.log(err);
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<TextField
placeholder={currentUser.displayName}
value={displayName}
color="secondary"
required
onChange={(e) => setdisplayName(e.target.value)}
/>
<TextField
type="text"
placeholder={currentUser.address}
value={address}
onChange={(e) => setAddress(e.target.value)}
required
/>
<Button type="submit">Submit</Button>
</form>
</div>
);
};
export default MyAccount;

How to use the updated state after setState call with react-hook

How to use the updated state after setState call. In my below code, I am getting the previous state value.
For array below technique works.
setState(currentState => [...currentState, {name, value}]);
But for object, its not working.
import React, { useState } from "react";
export default function App() {
const [state, setState] = useState({});
const handleChange = e => {
const { name, value } = e.target;
setState(currentState => ({ ...currentState, [name]: value }));
console.log(state[name]);
};
const handleSubmit = e => {
e.preventDefault();
console.log(state);
};
return (
<div className="App">
<form onSubmit={handleSubmit}>
a
<input
type="text"
name="a"
value={state["a"] || ""}
onChange={handleChange}
/>
b
<input
type="text"
name="b"
value={state["b"] || ""}
onChange={handleChange}
/>
<button type="submit">Save</button>
</form>
</div>
);
}
You can do like: setState({ ...state, [name]: value }); it should work for object
You can make use of useEffect to do something after the state is updated.
const [state, setState] = useState({});
...
useEffect(() => {
console.log('Do something after state has changed', state);
}, [state]);
PS: This will run in the first render though.
You can take a look this code for your reference. https://codesandbox.io/s/sleepy-saha-q7h72
function App() {
const [state, setState] = React.useState({ firstName: "", lastName: "" });
const handleChange = e => {
setState({ ...state, [e.target.name]: e.target.value });
};
return (
<div className="App">
<input
type="text"
placeholder="first name"
onChange={handleChange}
value={state.firstName}
name="firstName"
/>
<br />
<input
type="text"
placeholder="last name"
onChange={handleChange}
value={state.lastName}
name="lastName"
/>
<hr />
{state.firstName}--{state.lastName}
</div>
);
}

Handle an input with React hooks

I found that there are several ways to handle user's text input with hooks. What is more preferable or proper way to handle an input with hooks? Which would you use?
1) The simplest hook to handle input, but more fields you have, more repetitive code you have to write.
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
events:
onChange={event => setPassword(event.target.value)}
onChange={event => setUsername(event.target.value)}
2) Similar to above example, but with dynamic key name
const [inputValues, setInputValues] = useState({
username: '', password: ''
});
const handleOnChange = event => {
const { name, value } = event.target;
setInputValues({ ...inputValues, [name]: value });
};
event:
onChange={handleOnChange}
3) An alternative to useState, and as said on ReactJS docs, useReducer is usually preferable to useState.
const [inputValues, setInputValues] = useReducer(
(state, newState) => ({ ...state, ...newState }),
{username: '', password: ''}
);
const handleOnChange = event => {
const { name, value } = event.target;
setInputValues({ [name]: value });
};
event:
onChange={handleOnChange}
4) useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed.
const [inputValues, setInputValues] = useState({
username: '', password: ''
});
const handleOnChange = useCallback(event => {
const { name, value } = event.target;
setInputValues({ ...inputValues, [name]: value });
});
event:
onChange={handleOnChange}
How about writing a reusable function that returns the input value ... and the <input> itself:
function useInput({ type /*...*/ }) {
const [value, setValue] = useState("");
const input = <input value={value} onChange={e => setValue(e.target.value)} type={type} />;
return [value, input];
}
That can then be used as:
const [username, userInput] = useInput({ type: "text" });
const [password, passwordInput] = useInput({ type: "text" });
return <>
{userInput} -> {username} <br />
{passwordInput} -> {password}
</>;
This is how i'm using right now:
const [inputValue, setInputValue] = React.useState("");
const onChangeHandler = event => {
setInputValue(event.target.value);
};
<input
type="text"
name="name"
onChange={onChangeHandler}
value={inputValue}
/>
Yes you can handle react hooks with useState()
import React, {useState} from 'react'
export default () => {
const [fName, setfName] = useState('');
const [lName, setlName] = useState('');
const [phone, setPhone] = useState('');
const [email, setEmail] = useState('');
const submitValue = () => {
const frmdetails = {
'First Name' : fName,
'Last Name' : lName,
'Phone' : phone,
'Email' : email
}
console.log(frmdetails);
}
return(
<>
<hr/>
<input type="text" placeholder="First Name" onChange={e => setfName(e.target.value)} />
<input type="text" placeholder="Last Name" onChange={e => setlName(e.target.value)} />
<input type="text" placeholder="Phone" onChange={e => setPhone(e.target.value)} />
<input type="text" placeholder="Email" onChange={e => setEmail(e.target.value)} />
<button onClick={submitValue}>Submit</button>
</>
)
}
Here's how I do it (assuming your inputs must be inside a form):
I have a BasicForm component that I use.
It stores all the inputs state into an object into a single useState() call.
It passes via useContext() the inputs state along with an onChange() function and a function setInputInitialState() for the inputs to set their initial state when they are first mounted. It also passes onFocus, onBlur, and it has functions to validate fields which I'm not showing here to simplify the code.
This way I can easily create a form with as many inputs as I want, like:
<BasicForm
isSubmitting={props.isSubmitting}
submitAction={ (formState) =>
props.doSignIn(formState) }
>
<TextInput
type='email'
label='Email'
name='email'
placeholder='Enter email...'
required
/>
<TextInput
type='password'
label='Password'
name='password'
placeholder='Enter password...'
min={6}
max={12}
required
/>
<SubmitButton
label='Login'
/>
</BasicForm>
BasicForm.js
import FormContext from './Parts/FormContext';
function BasicForm(props) {
const [inputs, setInputs] = useState({});
function onChange(event) {
const newValue = event.target.value;
const inputName = event.target.name;
setInputs((prevState)=> {
return({
...prevState,
[inputName]: {
...prevState[inputName],
value: newValue,
dirty: true
}
});
});
}
function setInputInitialState(
inputName,
label='This field ',
type,
initialValue = '',
min = false,
max = false,
required = false) {
const INITIAL_INPUT_STATE = {
label: label,
type: type,
onFocus: false,
touched: false,
dirty: false,
valid: false,
invalid: false,
invalidMsg: null,
value: initialValue,
min: min,
max: max,
required: required
};
setInputs((prevState) => {
if (inputName in prevState) {
return prevState;
}
return({
...prevState,
[inputName]: INITIAL_INPUT_STATE
});
});
}
return(
<FormContext.Provider value={{
onChange: onChange,
inputs: inputs,
setInputInitialState: setInputInitialState,
}}>
<form onSubmit={onSubmit} method='POST' noValidate>
{props.children}
</form>
</FormContext.Provider>
);
}
TextInput.js
The inputse use the useEffect() hook to set their initial state when they're mounted.
function TextInput(props) {
const formContext = useContext(FormContext);
useEffect(() => {
console.log('TextInput useEffect...');
formContext.setInputInitialState(
props.name,
props.label,
props.type,
props.initialValue,
props.min,
props.max,
props.required
);
},[]);
return(
<input
type={props.type}
id={props.name}
name={props.name}
placeholder={props.placeholder}
value={([props.name] in formContext.inputs) ?
formContext.inputs[props.name].value
: props.initialValue || ''}
onChange={formContext.onChange}
onFocus={formContext.onFocus}
onBlur={formContext.onBlur}
>
</input>
</div>
{([props.name] in formContext.inputs) ?
formContext.inputs[props.name].invalidMsg && <div><span> {formContext.inputs[props.name].invalidMsg}</span></div>
: null}
</div>
);
...
}
function App(){
const [name, setName] = useState("");
const [istrue, Setistrue] = useState(false);
const [lastname,setLastname]=useState("");
function handleclick(){
Setistrue(true);
}
return(
<div>
{istrue ? <div> <h1>{name} {lastname}</h1> </div> :
<div>
<input type="text" placeholder="firstname" name="name" onChange={e =>setName(e.target.value)}/>
<input type="text" placeholder="lastname" name="lastname" onChange={e =>setLastname(e.target.value)}/>
<button type="submit" onClick={handleclick}>submit</button>
</div>}
</div>
)
}
}
You may want to consider a form library like Formik

Resources