Set state using onChange using hook - javascript

I want to get the value when I change it with onChange and created a name and contact number by using the value and setContacts, this app does not cause error but it does not work, Where is the problem? Thanks.
Each new contact in an object has an id, a name and a phone number
const AddUSer = () => {
const {contacts, setcontacts}=useState([]);
const { userName, setUSerName } = useState("");
const { userPhone, setUserPhone } = useState("");
const setName = (e) => {
const value = e.target.value;
return setUSerName(value);
};
const setPhone = (e) => {
const value = e.target.value;
return setUserPhone(value);
};
const handleNewcontact = () => {
const allcontacts = [...contacts];
const newContact = {
id: Math.floor(Math.random() * 1000),
fullName: userName,
phone: userPhone,
};
allcontacts.push(newContact);
setcontacts(allcontacts);
setUSerName("");
setUserPhone("");
}
};
return (
<div className="container">
<form>
<label>Name</label>
<input className="form-control" onChange={(e) => setName} />
<label>Phone</label>
<input className="form-control" onChange={(e) => setPhone} />
<button
onClick={handleNewcontact}
className="btn btn-primary mt-3 mb-4"
>
Save
</button>
</form>
</div>
);
};
export default AddUSer;

You are not passing the event to the function. You can either do
onChange={(e) => setName(e)}
onChange={(e) => setPhone(e)}
but better:
onChange={setName}
onChange={setPhone}

try this. the values are consoled when the user clicks the submit button.
const AddUSer = () => {
const [contact, setContact] = useState({id: '', userName:'', userPhone:''});
function handleNewContact(event) {
setContact({
...contact, id: Math.floor(Math.random() * 1000),
[event.target.name]: event.target.value
});
}
function handleSubmit(event) {
event.preventDefault();
console.log(contact);
}
return (
<div className="container">
<form>
<label>Name</label>
<input className="form-control" name='userName'
onChange={handleNewContact} />
<label>Phone</label>
<input className="form-control" name='userPhone'
onChange={handleNewContact} />
<button
onClick={handleSubmit}
className="btn btn-primary mt-3 mb-4"
>
Save
</button>
</form>
</div>
);
};
export default AddUSer;

Related

Having Issues with Form Validation for a SignUp component

I have a Sign Up Component in my current project, and I'm trying to implement validation for the email and phone number.
Code:
export default function Form() {
// States for registration
const [firstname, setFirstName] = useState('');
const [lastname, setLastName] = useState('');
const [email, setEmail] = useState('');
const [phonenumber, setPhoneNumber] = useState('');
// States for checking the errors
const [submitted, setSubmitted] = useState(false);
const [error, setError] = useState(false);
// Handling the email change
const handleEmail = (e) => {
setEmail(e.target.value);
setSubmitted(false);
};
// Handling the phonenumber change
const handlePhoneNumber = (e) => {
setPhoneNumber(e.target.value);
setSubmitted(false);
};
// Handling the form submission
const handleSubmit = (e) => {
e.preventDefault();
if (email === '' || phonenumber === '') {
setError(true);
} else {
setSubmitted(true);
setError(false);
}
};
// Showing error message if error is true
const errorMessage = () => {
return (
<div
className="error"
style={{
display: error ? '' : 'none',
}}>
<h1>Please enter all the fields</h1>
</div>
);
};
return (
<div className="form">
<div className="messages">
{errorMessage()}
{successMessage()}
</div>
<div className='inputval'>
<div className="d-flex justify-content-center flex-column">
<label className="label">Email</label>
<input onChange={handleEmail} className="input"
value={email} type="email" />
<label className="label">Phone Number</label>
<input onChange={handlePhoneNumber} className="input"
value={phonenumber} type="email" />
</div>
<div className="d-inline-block justify-content-center align-items-center">
<button className="btn" onClick={handleSubmit} type="submit">
Submit
</button>
</div>
</div>
</div>
);
}
For the most part, I tried implementing /^(([^<>()[\]\.,;:\s#\"]+(\.[^<>()[\]\.,;:\s#\"]+)*)|(\".+\"))#(([^<>()[\]\.,;:\s#\"]+\.)+[^<>()[\]\.,;:\s#\"]{2,})$/i for the format constant in my email but I had no luck. I have a useState hook that checks if the boxes are empty, but if I could get some assistance on this, it would be much appreciated!
There are a lot of form validation npm tools that will help alot. But if you want to do everything custom and understand about how it will work, here is a quick project demonstrating how to go about it. I would recommend putting some of the helper functions in different files so they can be used everywhere in your app. CodeSandbox: https://codesandbox.io/s/simple-form-validation-jqfvpy?file=/src/Input.js:0-325
export default function App() {
const [form, setForm] = useState({ name: "", email: "", phone: "" });
const [errors, setErrors] = useState({ name: [], email: [], phone: [] });
const checkRules = (input, rules) => {
let errors = [];
let value = input;
if (typeof value === "string") value = input.trim();
if (rules.required) {
if (value === "") errors.push("*This field is required.");
}
if (rules.phone) {
let phoneno = new RegExp(/^\(?(\d{3})\)?[-. ]?(\d{3})[-. ]?(\d{4})$/);
if (!phoneno.test(value))
errors.push("*Please Enter valid phone number XXX-XXX-XXXX");
}
if (rules.email) {
let pattern = new RegExp(
/^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(#((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(#\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i
);
if (!pattern.test(value)) errors.push("*Please enter a valid email.");
}
return errors;
};
const checkFormValidation = (f) => {
const errors = {};
errors.name = checkRules(f.name, { required: true });
errors.phone = checkRules(f.phone, { phone: true });
errors.email = checkRules(f.email, { email: true });
for (const [, value] of Object.entries(errors)) {
if (value.length > 0) return { noErrors: false, errors };
}
return { noErrors: true, errors };
};
const handleSubmit = (f) => {
const { errors, noErrors } = checkFormValidation(f);
setErrors(errors);
if (noErrors) {
alert(JSON.stringify(f));
}
};
return (
<div className="App">
<div style={{ display: "grid", placeItems: "center" }}>
<Input
name="Name"
value={form.name}
errors={errors.name}
onChange={(e) => setForm({ ...form, name: e.target.value })}
/>
<Input
name="Email"
value={form.email}
errors={errors.email}
onChange={(e) => setForm({ ...form, email: e.target.value })}
/>
<Input
name="Phone"
value={form.phone}
errors={errors.phone}
onChange={(e) => setForm({ ...form, phone: e.target.value })}
/>
<button onClick={() => handleSubmit(form)}>Submit</button>
</div>
</div>
);
}
export const Input = ({ name, value, onChange, errors }) => {
return (
<>
<input type="text" placeholder={name} value={value} onChange={onChange} />
{errors.length > 0
? errors.map((e) => (
<p style={{ fontSize: "9px", color: "red" }}>{e}</p>
))
: null}
</>
);
};

Cant Update The state after getting data from the input React js

as u see in the code I'm tryin to get the "ProductionName" from the server "getManuficturedProduction" and display that into the input and after that I want to get the input value and post it to the server but idk why my set state doesn't update and still show me the default value.when i log my set state "assignProductToProductionline" i can see that my "ProductionName" did not updated
const [assignProductToProductionline, SetAssignProductToProductionline] =
useState({
Id: "",
ProductionCode: "",
ProductionName: "",
});
useEffect(() => {
loadProductionLine();
}, []);
const [productionLineName, SetProductionLineName] = useState([]);
const loadProductionLine = async () => {
const result = await axios.get(
"url"
);
SetProductionLineName(result.data);
};
const getManuficturedProduction = async () => {
var res = await axios.get(
`url`
);
var GetInfo = res.data.Result;
SetAssignProductToProductionline({
ProductionName: `${GetInfo.Name}`,
});
};
const { Id, ProductionCode, ProductionName } = assignProductToProductionline;
const onInputChange = (e) => {
SetAssignProductToProductionline({
...assignProductToProductionline,
[e.target.name]: e.target.value,
});
};
const onSubmit = async (e) => {
await axios
.post(
"url",
assignProductToProductionline
)
.catch(function (error) {
if (error.response) {
return toast.error(error.response.data);
}
});
navigate("/productionLineProduct");
};
};
return (
<div className="container">
<div className="w-75 mx-auto shadow p-5 mt-5">
<form onSubmit={(e) => onSubmit(e)}>
<div className="form-group">
<select
className="form-control form-control-md mb-2 "
type="text"
name="Id"
value={Id}
onChange={(e) => onInputChange(e)}
autoComplete="off"
>
{productionLineName.map((cs) => (
<option key={cs.Id} value={cs.Id}>
{cs.ProductionLineName}
</option>
))}
</select>
</div>
<div className="form-group mb-2">
<input
id="customeProductionCode"
type="number"
className="form-control form-control-md"
name="ProductionCode"
value={ProductionCode}
onChange={(e) => onInputChange(e)}
autoComplete="off"
onInput={(e) => (e.target.value = e.target.value.slice(0, 9))}
/>
<a
className="btn btn-outline-success px-4"
onClick={(e) => getManuficturedProduction(e)}
>
check it
</a>
<div className="mt-2">
<input
className="text-success w-50"
name="ProductionName"
defaultValue=""
value={ProductionName}
placeholder={ProductionName}
onChange={(e) => onInputChange(e)}
/>
</div>
</div>
<button className="btn btn-primary w-25 ">save</button>
</form>
</div>
</div>
);
};
export default AssignProductToProductionLine;
{
you have to use assignProductToProductionline.ProductionName.
This line
const { Id, ProductionCode, ProductionName } = assignProductToProductionline;
creates a constant that is initialized with the first value and never changed.

Reactjs form is not getting cleared after submission

I am new to Reactjs and just now I have started with React two way binding forms.I have coded for a form, I wanted the form clear after submission.
Even after submission it's not getting clear.
Please point out mistake in the code.
Also check if I have implemented 2 way binding correctly.
Correct me if I am wrong.
ExpenseForm.js
import React, { useState } from "react";
const ExpenseForm = () => {
const [userInput, setuserInput] = useState({enteredTitle : '' , enteredAmount : '',enteredDate : ''});
const TitleChangeHandler = (event) => {
setuserInput((prevState) => {
return { ...prevState, enteredTitle: event.target.value };
});
};
const AmountChangeHandler = (event) => {
setuserInput((prevState) => {
return { ...prevState, enteredAmount: event.target.value };
});
};
const DateChangeHandler = (event) => {
setuserInput((prevState) => {
return { ...prevState, enteredDate: event.target.value };
});
};
const submitHandler = (event) => {
event.preventDefault();
const expenseData = {
title: userInput.enteredTitle,
amount: userInput.enteredAmount,
date: new Date(userInput.enteredDate),
};
console.log(expenseData);
setuserInput({enteredTitle : '' , enteredAmount : '',enteredDate : ''})
console.log(expenseData);
};
return (
<form onSubmit={submitHandler}>
<div className="new-expense__controls">
<div className="new-expense__control">
<label>Title</label>
<input
type="text"
value={setuserInput.enteredTitle}
onChange={TitleChangeHandler}
/>
</div>
<div className="new-expense__control">
<label>Amount</label>
<input
type="number"
value={setuserInput.enteredAmount}
onChange={AmountChangeHandler}
min="0.01"
stepmin="0.01"
/>
</div>
<div className="new-expense__control">
<label>Date</label>
<input
type="date"
value={setuserInput.enteredDate}
onChange={DateChangeHandler}
min="2019-01-01"
max="2022-12-31"
/>
</div>
<div className="new-expense__actions">
<button type="submit">Submit</button>
</div>
</div>
</form>
);
};
export default ExpenseForm;
I don't know what two-way binding is and I'm not quite sure why your inputs aren't resetting, usually when you reset the input's value it changes. But you can call event.target.reset() at the end of your submit handler to reset the form. Also, you can refactor your code to have only one onChangeHandler by assigning each input with a name attribute and then using that name within the onChangeHandler to dictate the key in the 'userInput' object:
const ExpenseForm = () => {
const [userInput, setuserInput] = useState({
enteredTitle: "",
enteredAmount: "",
enteredDate: ""
});
const onChangeHandler = (event) => {
setuserInput((prevState) => {
return { ...prevState, [event.target.name]: event.target.value };
});
};
const submitHandler = (event) => {
event.preventDefault();
const expenseData = {
title: userInput.enteredTitle,
amount: userInput.enteredAmount,
date: new Date(userInput.enteredDate)
};
console.log(expenseData);
setuserInput({ enteredTitle: "", enteredAmount: "", enteredDate: "" });
console.log(expenseData);
event.target.reset();
};
return (
<form onSubmit={submitHandler}>
<div className="new-expense__controls">
<div className="new-expense__control">
<label>Title</label>
<input
name="enteredTitle"
type="text"
value={setuserInput.enteredTitle}
onChange={onChangeHandler}
/>
</div>
<div className="new-expense__control">
<label>Amount</label>
<input
name="enteredAmount"
type="number"
value={setuserInput.enteredAmount}
onChange={onChangeHandler}
min="0.01"
stepmin="0.01"
/>
</div>
<div className="new-expense__control">
<label>Date</label>
<input
name="enteredDate"
type="date"
value={setuserInput.enteredDate}
onChange={onChangeHandler}
min="2019-01-01"
max="2022-12-31"
/>
</div>
<div className="new-expense__actions">
<button type="submit">Submit</button>
</div>
</div>
</form>
);
};
export default ExpenseForm;

am getting an error props.onSubmitForm is not a function while trying to pass data from child to parent component in react

I am trying to store input data in two states; name and age when onChange event is fired.
Thereafter I am trying to pass the stored data upon one level when an onSubmit event of a form is fired.
What I have realized is that when the form is submitted and it is now the time to pass the data up one level, I get an error "props.onSubmitForm is not a function".
I have noted this is a common error but i have tried comparing answers and code to no avail.
here is the child component with the form.
const UserDetails = (props) => {
const [name, setName] = useState("");
const [age, setAge] = useState("");
const submittedFormhandler = (event) => {
event.preventDefault();
let userDetails = {
name: name,
age: age
};
props.onSubmitForm(userDetails);
};
const getNameHandler = (event) => {
return setName(event.target.value);
};
const getAgeHandler = (event) => {
return setAge(event.target.value);
};
return (
<form onSubmit={submittedFormhandler}>
<div>
<label htmlFor="name">User name</label>
<input type="text" name="name" id="" onChange={getNameHandler} />
</div>
<div>
<label htmlFor="age">Age</label>
<input type="number" name="age" id="" onChange={getAgeHandler} />
</div>
<button type="submit">Add User</button>
</form>
);
};
export default UserDetails;
here is the parent component
import UserDetails from "../UserDetails";
const DisplayDetails = () => {
const submittedDataHandler = (inputData) => {
return console.log(inputData);
};
return <UserDetails onSubmitForm={submittedDataHandler} />;
};
export default DisplayDetails;
Your code works super fine, but I guess that's because you've used the wrong component
It should be DisplayDetails not UserDetails
This one works fine:
const DisplayDetails = () => {
const submittedDataHandler = (inputData) => {
return console.log(inputData);
};
return <UserDetails onSubmitForm={submittedDataHandler} />;
};
const UserDetails = (props) => {
const [name, setName] = React.useState("");
const [age, setAge] = React.useState("");
const submittedFormhandler = (event) => {
event.preventDefault();
let userDetails = {
name: name,
age: age
};
props.onSubmitForm(userDetails);
};
const getNameHandler = (event) => {
return setName(event.target.value);
};
const getAgeHandler = (event) => {
return setAge(event.target.value);
};
return (
<form onSubmit={submittedFormhandler}>
<div>
<label htmlFor="name">User name</label>
<input type="text" name="name" id="" onChange={getNameHandler} />
</div>
<div>
<label htmlFor="age">Age</label>
<input type="number" name="age" id="" onChange={getAgeHandler} />
</div>
<button type="submit">Add User</button>
</form>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<DisplayDetails />, rootElement); // <-- RIGHT COMPONENT!!!
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
And this one throw error like yours:
const DisplayDetails = () => {
const submittedDataHandler = (inputData) => {
return console.log(inputData);
};
return <UserDetails onSubmitForm={submittedDataHandler} />;
};
const UserDetails = (props) => {
const [name, setName] = React.useState("");
const [age, setAge] = React.useState("");
const submittedFormhandler = (event) => {
event.preventDefault();
let userDetails = {
name: name,
age: age
};
props.onSubmitForm(userDetails);
};
const getNameHandler = (event) => {
return setName(event.target.value);
};
const getAgeHandler = (event) => {
return setAge(event.target.value);
};
return (
<form onSubmit={submittedFormhandler}>
<div>
<label htmlFor="name">User name</label>
<input type="text" name="name" id="" onChange={getNameHandler} />
</div>
<div>
<label htmlFor="age">Age</label>
<input type="number" name="age" id="" onChange={getAgeHandler} />
</div>
<button type="submit">Add User</button>
</form>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<UserDetails />, rootElement); // <-- WRONG COMPONENT HERE!!!
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
The wrong version of your code which should be DisplayDetails:

Input form to clear once submitted using React

I created a simple to do list wherein the add and delete works. My problem is, after submitting a todo, the input box won't clear.
This is my app.js
const App = () => {
const [toDoList, setToDoList] = useState([]);
const [toDo, setToDo] = useState("");
const handleToDo = (event) => {
const { value } = event.target;
setToDo(value);
};
const submit = () => {
//const list = toDoList;
const newItem = {
id: 1 + Math.random(),
value: toDo,
};
if (newItem.value && !toDoList.includes(newItem.value)) {
toDoList.push(newItem);
setToDoList([...toDoList]);
}
};
return (
<div className="container">
Add an Item
<br />
<input
type="text"
placeholder="Type item here..."
onChange={handleToDo}
/>
<button className="add-btn btn-floating" onClick={submit}>
<i class="material-icons"> + </i>
</button>
<br />
<ul>
...display of todos here
</ul>
</div>
);
//}
};
export default App;
I'm confused as to where I should insert the useState so that the input would be reset.
The value of the input box must also be governed by the state. So the input should be like:
<input
value={toDo}
type="text"
placeholder="Type item here..."
onChange={handleToDo}
/>
Once You click on submit, reset the toDo to empty
const submit = () => {
//const list = toDoList;
const newItem = {
id: 1 + Math.random(),
value: toDo,
};
if (newItem.value && !toDoList.includes(newItem.value)) {
toDoList.push(newItem);
setToDoList([...toDoList]);
}
setToDo("");
};
Your input seems to be half-controlled. You should also give the input a value property as such:
<input
type="text"
placeholder="Type item here..."
onChange={handleToDo}
value={toDo}
/>
And now you can clear out the input when a task is submitted:
const submit = () => {
//rest of the code here...
setToDo('') //this'll clear out the value of your input
};
You can add a value to input element. And after submit, set it to an empty string. So:
const App = () => {
const [toDoList, setToDoList] = useState([]);
const [toDo, setToDo] = useState("");
const handleToDo = (event) => {
const { value } = event.target;
setToDo(value);
};
const submit = () => {
//const list = toDoList;
const newItem = {
id: 1 + Math.random(),
value: toDo,
};
if (newItem.value && !toDoList.includes(newItem.value)) {
toDoList.push(newItem);
setToDoList([...toDoList]);
setToDo("");
}
};
return (
<div className="container">
Add an Item
<br />
<input
type="text"
value={toDo}
placeholder="Type item here..."
onChange={handleToDo}
/>
<button className="add-btn btn-floating" onClick={submit}>
<i class="material-icons"> + </i>
</button>
<br />
<ul>
{toDoList.map((todoLi) => (
<li>{todoLi}</li>
))}
</ul>
</div>
);
//}
};
export default App;
You just have to pass empty string in setToDo, after all the code in your submit function setToDo("")

Categories

Resources