How prevent submit edit form when anything is not changed? - reactjs

I have a form like this that I created with context crud project. Here I want that if no changes have been made in the form, it should not be updated and a notification should be issued. How can I do this?
Note: also, if any input is empty, do not submit. How can I do this without required the input. How can I fix these problems?
import React from "react";
import { NavLink } from "react-router-dom";
import { useContext, useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { GlobalContext } from "../../context/GlobalState";
import styles from "../ContactForm/Form.module.scss";
import { toast } from "react-toastify";
const EditContactForm = () => {
const { contacts, UPDATE_CONTACT } = useContext(GlobalContext);
const [selectedContact, setSelectedContact] = useState({
id: "",
name: "",
surname: "",
fatherName: "",
specialty: "",
email: "",
gender: "",
test:''
});
const history = useNavigate();
const { id } = useParams();
useEffect(() => {
const userId = id;
const selectedContact = contacts.find((user) => String(user.id) === userId);
if (selectedContact) {
setSelectedContact(selectedContact);
}
}, [id, contacts]);
function onSubmit(e) {
e.preventDefault();
if(selectedContact){
UPDATE_CONTACT(selectedContact);
console.log("new user edited:", selectedContact);
history("/contacts");
toast('updated')
}
else if(selectedContact===contacts){
toast('anything doesnt changed') // problem is there
}
}
const handleOnChange = (e) => {
setSelectedContact((selectedContact) => ({
...selectedContact,
[e.target.name]: e.target.value,
}));
};
const inputHandleChange = (e) => {
setSelectedContact({
...selectedContact,
[e.target.name]: e.target.checked ? e.target.id : "",
});
};
const selectOptions = [
{ label: "One", value: 1 },
{ label: "Two", value: 2 },
{ label: "Three", value: 3 },
];
const onChange = (e) => setSelectedContact({ ...selectedContact, [e.target.name]: e.target.value })
return (
<div className={styles.form}>
<form onSubmit={onSubmit}>
<div class="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>Name</label>
<div class="col-sm-8">
<input
class="form-control"
name="name"
required
value={selectedContact?.name ?? ""}
onChange={handleOnChange}
/>
</div>
</div>
<div class="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>Surname</label>
<div class="col-sm-8">
<input
class="form-control"
name="surname"
required
value={selectedContact?.surname ?? ""}
onChange={handleOnChange}
/>
</div>
</div>
<div class="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>
Father Name
</label>
<div class="col-sm-8">
<input
class="form-control"
name="fatherName"
required
value={selectedContact?.fatherName ?? ""}
onChange={handleOnChange}
/>
</div>
</div>
<div class="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>Email</label>
<div class="col-sm-8">
<input
class="form-control"
name="email"
required
value={selectedContact?.email ?? ""}
onChange={handleOnChange}
/>
</div>
</div>
<div class="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>
Specialty
</label>
<div class="col-sm-8">
<input
class="form-control"
name="specialty"
required
value={selectedContact?.specialty ?? ""}
onChange={handleOnChange}
/>
</div>
</div>
<div className="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>position</label>
<div className="col-sm-8 d-flex justify-content-center align-items-center">
<select
onChange={onChange}
value={selectedContact.test}
name="test"
class="form-select"
aria-label="Default select example"
>
{selectOptions.map((item) => (
<option
key={item.value}
value={item.value}
>
{item.label}
</option>
))}
</select>
</div>
</div>
<div className="mb-3 row row d-flex justify-content-around">
<label className={`col-sm-2 p-0 ${styles.inputLabel}`}>Gender</label>
<div className="col-sm-8">
<div class="form-check form-check-inline ">
<input
class="form-check-input"
type="radio"
name="gender"
id="male"
checked={selectedContact.gender === "male"}
onChange={inputHandleChange}
/>
<label class="form-check-label">Male</label>
</div>
<div class="form-check form-check-inline">
<input
class="form-check-input"
type="radio"
name="gender"
id="female"
checked={selectedContact.gender === "female"}
onChange={inputHandleChange}
/>
<label class="form-check-label">Female</label>
</div>
</div>
</div>
<div className="mb-3 row d-flex justify-content-around">
<div class="form-check col-sm-11">
<input
class="form-check-input"
type="checkbox"
name="updatesNotification"
id="update"
checked={selectedContact.updatesNotification === "update"}
onChange={(e) =>
setSelectedContact({
...selectedContact,
[e.target.name]: e.target.checked ? e.target.id : "",
})
}
/>
<label class="form-check-label" for="flexCheckDefault">
I want to be notified of updates
</label>
</div>
</div>
<div className={styles.buttons}>
<button type="submit" class="btn btn-primary">
Update a contact
</button>
<NavLink to="/contacts" className="btn btn-danger m-2">
Cancel
</NavLink>
</div>
</form>
</div>
);
};
export default EditContactForm;
import React, { useState } from "react";
import { useContext } from "react";
import { GlobalContext } from "../../context/GlobalState";
import { useNavigate } from "react-router-dom";
import { NavLink } from "react-router-dom";
import { v4 as uuidv4 } from "uuid";
import styles from "../ContactForm/Form.module.scss";
import { toast } from "react-toastify";
import { Checkbox, Button, Form, Input, Select, Radio } from "antd";
const Form1 = () => {
const { ADD_CONTACT } = useContext(GlobalContext);
const [contact, setContact] = useState({
id: uuidv4(),
name: "",
surname: "",
fatherName: "",
specialty: "",
email: "",
gender: "",
updatesNotification: "",
test: "",
});
const { Option } = Select;
const { name, surname, fatherName, specialty, email } = contact;
let history = useNavigate();
const onSubmit = () => {
if (contact) {
ADD_CONTACT(contact);
history("/contacts");
console.log(contact);
toast.success("Contact successfully added");
}
else{
???
}
};
const selectOptions = [
{ label: "One", value: 1 },
{ label: "Two", value: 2 },
{ label: "Three", value: 3 },
];
return (
<>
<Form
onFinish={onSubmit}
className={styles.form}
name="myForm"
initialValues={{
remember: true,
}}
autoComplete="off"
labelCol={{
span: 2,
}}
wrapperCol={{
span: 16,
}}
>
<div className="row">
<Form.Item
label="Name"
rules={[{ required: true, message: "Please input your name!" }]}
>
<Input
placeholder="Enter Your Name"
value={name}
name="name"
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
</div>
<Form.Item
label="Surname"
rules={[{ required: true, message: "Please input your surname!" }]}
>
<Input
placeholder="Enter Your Surname"
value={surname}
name="surname"
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item
label="Father Name"
rules={[{ required: true, message: "Please input your surname!" }]}
>
<Input
placeholder="Enter Your FatherName"
value={fatherName}
name="fatherName"
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item
label="Email"
rules={[{ required: true, message: "Please input your mail!" }]}
>
<Input
name="email"
placeholder="your mail"
value={email}
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item
label="Specialty"
rules={[{ required: true, message: "Please input your specialty!" }]}
>
<Input
name="specialty"
placeholder="your specialt"
value={specialty}
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item label='Category'>
<Select
onChange={(e)=>setContact({ ...contact, test : e })}
defaultValue='category'
// value={contact.test}
name="test"
style={{
width: 120,
}}
>
{selectOptions.map((item) => (
<Option key={item.value} value={item.value}></Option>
))}
</Select>
</Form.Item>
<Form.Item label="Gender">
<Radio.Group
onChange={(e) =>
setContact({
...contact,
[e.target.name]: e.target.checked ? e.target.id : "",
})
}
name="gender"
rules={[{ required: true, message: "Please your gender!" }]}
>
<Radio
id="female"
value="Female"
checked={contact.gender === "female"}
>
Female
</Radio>
<Radio id="male" value="Male" checked={contact.gender === "male"}>
Male
</Radio>
</Radio.Group>
</Form.Item>
<Form.Item>
<Checkbox
name="updatesNotification"
checked={contact.updatesNotification === "update"}
id="update"
onChange={(e) =>
setContact({
...contact,
[e.target.name]: e.target.checked ? e.target.id : "",
})
}
>
I want to be notified of updates
</Checkbox>
</Form.Item>
<div className={styles.buttons}>
<Button type="primary" htmlType="submit">
Add contact
</Button>
<NavLink to="/contacts">
<Button danger>Cancel</Button>
</NavLink>
</div>
</Form>
</>
);
};
export default Form1;
enter image description here

One way to check if two objects are equal is to transform them into string.
JSON.stringify(selectedContact) === JSON.stringify(contacts.find((user) => user.id === selectedContact.id))
For checking if one if the data is empty one way is using the method some, this method send true if one the item in an array match the condition.
if (Object.keys(selectedContact).some(key => !selectedContact[key])) {
alert('There are missing information')
}

Related

Why the ant design select option doesnt save selected option?

I have developed a project with context crud. Everything is fine, only the select option does not work, that is, after any option is selected and added, the selected option does not appear in the edit section. What is the problem ?
I have error this : 'Cannot read properties of undefined (reading 'name')'
import React, { useState } from "react";
import { useContext } from "react";
import { GlobalContext } from "../../context/GlobalState";
import { useNavigate } from "react-router-dom";
import { NavLink } from "react-router-dom";
import { v4 as uuidv4 } from "uuid";
import styles from "../ContactForm/Form.module.scss";
import { toast } from "react-toastify";
import { Checkbox, Button, Form, Input, Select, Radio } from "antd";
const Form1 = () => {
const { ADD_CONTACT } = useContext(GlobalContext);
const [contact, setContact] = useState({
id: uuidv4(),
name: "",
surname: "",
fatherName: "",
specialty: "",
email: "",
gender: "",
updatesNotification: "",
test: "",
});
const { Option } = Select;
const { name, surname, fatherName, specialty, email } = contact;
let history = useNavigate();
const onSubmit = () => {
if (contact) {
ADD_CONTACT(contact);
history("/contacts");
console.log(contact);
toast.success("Contact successfully added");
}
};
const selectOptions = [
{ label: "One", value: 1 },
{ label: "Two", value: 2 },
{ label: "Three", value: 3 },
];
return (
<>
<Form
onFinish={onSubmit}
className={styles.form}
name="myForm"
initialValues={{
remember: true,
}}
autoComplete="off"
labelCol={{
span: 2,
}}
wrapperCol={{
span: 16,
}}
>
<div className="row">
<Form.Item
label="Name"
rules={[{ required: true, message: "Please input your name!" }]}
>
<Input
placeholder="Enter Your Name"
value={name}
name="name"
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
</div>
<Form.Item
label="Surname"
rules={[{ required: true, message: "Please input your surname!" }]}
>
<Input
placeholder="Enter Your Surname"
value={surname}
name="surname"
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item
label="Father Name"
rules={[{ required: true, message: "Please input your surname!" }]}
>
<Input
placeholder="Enter Your FatherName"
value={fatherName}
name="fatherName"
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item
label="Email"
rules={[{ required: true, message: "Please input your mail!" }]}
>
<Input
name="email"
placeholder="your mail"
value={email}
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item
label="Specialty"
rules={[{ required: true, message: "Please input your specialty!" }]}
>
<Input
name="specialty"
placeholder="your specialt"
value={specialty}
onChange={(e) =>
setContact({ ...contact, [e.target.name]: e.target.value })
}
/>
</Form.Item>
<Form.Item label='Category'>
<Select
onChange={(e)=>setContact({ ...contact, [e.target.name]: e.target.value })}
defaultValue='category'
value={contact.test}
name="test"
style={{
width: 120,
}}
>
{selectOptions.map((item) => (
<Option key={item.value} value={item.value}></Option>
))}
</Select>
</Form.Item>
<Form.Item label="Gender">
<Radio.Group
onChange={(e) =>
setContact({
...contact,
[e.target.name]: e.target.checked ? e.target.id : "",
})
}
name="gender"
rules={[{ required: true, message: "Please your gender!" }]}
>
<Radio
id="female"
value="Female"
checked={contact.gender === "female"}
>
Female
</Radio>
<Radio id="male" value="Male" checked={contact.gender === "male"}>
Male
</Radio>
</Radio.Group>
</Form.Item>
<Form.Item>
<Checkbox
name="updatesNotification"
checked={contact.updatesNotification === "update"}
id="update"
onChange={(e) =>
setContact({
...contact,
[e.target.name]: e.target.checked ? e.target.id : "",
})
}
>
I want to be notified of updates
</Checkbox>
</Form.Item>
<div className={styles.buttons}>
<Button type="primary" htmlType="submit">
Add contact
</Button>
<NavLink to="/contacts">
<Button danger>Cancel</Button>
</NavLink>
</div>
</Form>
</>
);
};
export default Form1;
onChange Event in Antd Select only gives the Selected Value, it will not return any event
So Modifying your code into below will fix your issue..
<Select
onChange={(e)=>setContact({ ...contact, test : e })}
defaultValue='category'
value={contact.test}
name="test"
style={{
width: 120,
}}
>
{selectOptions.map((item) => (
<Option key={item.value} value={item.value}></Option>
))}
</Select>

React Firebase is not getting data from React Hook form

This is what I'm stuck with for last couple of hours. I have tried default values from react hook form. I kinda getting the user input on the console but for firebase it's showing error. It is working with the normal input system
import React, { useEffect } from "react";
import {
useAuthState,
useCreateUserWithEmailAndPassword,
} from "react-firebase-hooks/auth";
import { useForm } from "react-hook-form";
import { Link, useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import auth from "../../firebase.init";
import Loading from "../Shared/Loading";
import GoogleLogin from "./GoogleLogin";
const Signup = () => {
const [createUserWithEmailAndPassword,loading] =
useCreateUserWithEmailAndPassword(auth);
const navigate = useNavigate();
const [user] = useAuthState(auth);
useEffect(() => {
if (user) {
navigate("/home");
}
}, [navigate, user]);
const {
register,
formState: { errors },
handleSubmit,
} = useForm();
const onSubmit = (data) => {
createUserWithEmailAndPassword(data);
if (user) {
toast.success("Successfully Registered");
}
console.log(data);
};
if(loading){
return <Loading></Loading>
}
return (
<section className="container mx-auto px-5 gap-5 md:px-12">
<form className="py-5 card" onSubmit={handleSubmit(onSubmit)}>
<div className="mt-5 mb-5">
<input
type="text"
className="input input-bordered py-5"
placeholder="Your Full Name"
{...register("name", {
required: { value: true, message: "Name is required" },
maxLength: 80,
pattern: {
value: /^[\w'\-,.][^0-9_!¡?÷?¿/\\+=##$%ˆ&*(){}|~<>;:[\]]{2,}$/,
message: `Don't use special characters`,
},
})}
/>
<br />
</div>
<div className="form-control w-full max-w-xs">
<label className="label">
<span className="label-text">Email</span>
</label>
<input
type="email"
placeholder="Your Email"
className="input input-bordered w-full max-w-xs"
{...register("email", {
required: {
value: true,
message: "Email is Required",
},
pattern: {
value: /[a-z0-9]+#[a-z]+\.[a-z]{2,3}/,
message: "Provide a valid Email",
},
})}
/>
<label className="label">
{errors.email?.type === "required" && (
<span className="label-text-alt text-red-500">
{errors.email.message}
</span>
)}
{errors.email?.type === "pattern" && (
<span className="label-text-alt text-red-500">
{errors.email.message}
</span>
)}
</label>
</div>
<div>
<input
type="password"
placeholder="Password"
className="input input-bordered"
{...register("password", {
required: {
value: true,
message: `Please provide a password between 6 to 30 character`,
},
})}
/>
<label className="label">
{errors.password?.type === "required" && (
<span className="label-text-alt text-red-500">
{errors.password.message}
</span>
)}
{errors.password?.type === "pattern" && (
<span className="label-text-alt text-red-500">
{errors.password.message}
</span>
)}
</label>
</div>
<input className="btn btn-primary" value="Register" type="submit" />
</form>
<GoogleLogin></GoogleLogin>
<div>
<Link className="btn btn-se" to="/login">
Login
</Link>
</div>
</section>
);
};
export default Signup;
So after submitting, I can see the data on console but can't send them to firebase.

Diffrent Input type using Bootstrap desing in Redux-React functional componnent

Im trying to display my data in diffrent Form inputs, but in some of them, i dont know how to reach my data.
//DashShowDetails.js:
import { useState, useEffect } from 'react';
import { Button, Form } from 'react-bootstrap';
import { Input, Label } from 'reactstrap';
function DashShowDetails(props) {
const { data } = props;
const [edit, setEdit] = useState(false);
const [formData, setFormData] = useState({
id: data._id,
showId: data.showId,
showName: data.name,
showGenres: data.genres,
showStatus: data.status,
showPremiered: data.premiered,
showEnded: data.ended,
showRating: data.rating,
showSummery: data.summary,
showImage: data.image,
});
const onClick = () => {
setEdit(current => !current)
}
const onChange = (e) => {
setFormData((prevState) => ({
...prevState,
[e.target.name]: e.target.value
}))
}
const onSubmit = async (e) => {
e.preventDefault()
let show = formData;
dispatch(updateDashShow(show));
setEdit(current => !current);
setFormData((prevState) => ({
...prevState,
}))
}
useEffect(() => {
}, [edit]);
return (
<div>
<div>
<h5>{data.name}</h5>
<Button onClick={onClick}>Edit Show</Button>
</div>
<div>
{edit === true && (
<div>
<h3>Edit {data.name}</h3>
<Form onSubmit={onSubmit} >
<div>
<Label>Show ID:</Label>
<Input type="text" name="showId" value={data.showId} onChange={onChange} />
</div>
<div>
<Label>Show Name:</Label>
<Input type="text" name="showName" defaultValue={data.name} onChange={onChange} />
</div>
<div>
<Label>Show Genres:</Label>
<Input type="text" name="showGenres" defaultValue={data.genres} onChange={onChange} />
</div>
<div>
<Label>Show Status:</Label>
<Input type="select" name="showStatus" select={data.status} onChange={onChange}>
<option value="running">Running</option>
<option value="ended">Ended</option>
</Input>
</div>
<div>
<Label>Premiered Date:</Label>
<Input type="date" name="showPremiered" value={data.premiered} onChange={onChange} />
</div>
<div>
<Label>Ended Date:</Label>
<Input type="date" name="showEnded" value={data.ended} onChange={onChange} />
</div>
<div>
<Label>Show Rating:</Label>
<Input type="array" name="showRating" value={data.rating} onChange={onChange} />
</div>
<div>
<Label>Show Summery:</Label>
<Input type="textarea" name="showSummery" value={data.summery} onChange={onChange} />
</div>
<div>
<Label>Image:</Label>
</div>
<Button type="submit">Update Show</Button>
<Button>Delete Show</Button>
</Form>
</div>
)}
</div>
</div>
);
}
export default DashShowDetails;
My output when i click 'Edit Show' is:
How can i display my Data in inputs: Premiered Date, Show Rating, Show Summery & Image?
My Schema file in Node.js: (sending new data to MoongoDB)
const showSchema = new mongoose.Schema({
showId: {type: Number},
name: {type: String},
genres: {type: Array},
status: {type: String},//Boolean
premiered: {type: Date},
ended: {type: Date},
rating: {type: Array},
summary: {type: String},
image: {type: Array},//Link?File?
})
module.exports = mongoose.model('shows', showSchema);

React Get User Info.(Input Values) On a Button Click

I've made a simple resume portal. What I want is to get all the inputs values displayed on a screen on submit. This all should be done when button(Generate CV) is clicked.
Here's my code below:
Child component ( src -> Routes -> UserForm -> Components -> UserDetails -> index.js )
import React from 'react'
import './style.scss';
import { Row, Col } from 'react-bootstrap'
const UserDetails = (props) => {
const { wrkExpTxtArea, AcQuTxtArea, clickToAdd, clickToRmv, addAcQuTxtArea, rmvAcQuTxtArea, inputChangeHandler } = props
return (
<>
<div className='UserDetails'>
<Row>
<Col lg='6'>
<div className='persnlInfo'>
<h4>
Personal Information
</h4>
<p>Your Name</p>
<input onChange={() => inputChangeHandler('name')} type="text" placeholder="Enter here" />
<p>Your Contact</p>
<input type="text" placeholder="Enter here" />
<p>Your Address</p>
<textarea className='formAddress' rows="5" cols="10" placeholder="Enter here" />
<p id='impLinks'>Important Links</p>
<p>Facebook</p>
<input type="text" placeholder="Enter here" />
<p>Instagram</p>
<input type="text" placeholder="Enter here" />
<p>Linkedin</p>
<input type="text" placeholder="Enter here" />
</div>
</Col>
<Col lg='6'>
<h4>
Professional Information
</h4>
<p>Objective</p>
<textarea className='formObjective' rows="5" cols="10" placeholder="Enter here" />
<p>Work Experience</p>
{wrkExpTxtArea.map(item => (
<textarea className='formWrkExp' value={item.value} rows="3" cols="10" placeholder="Enter here" />
))}
<div className='Button' >
<input type='button' value='Add' onClick={clickToAdd} />
<input type='button' value='Remove' onClick={clickToRmv} />
</div>
<p id='AcQu'>Academic Qualification</p>
{AcQuTxtArea.map(item => (
<textarea className='formAcQu' value={item.value} rows="3" cols="10" placeholder="Enter here" />
))}
<div className='Button' >
<input type='button' value='Add' onClick={addAcQuTxtArea} />
<input type='button' value='Remove' onClick={rmvAcQuTxtArea} />
</div>
</Col>
<Row>
<div className='sbmtButton'>
<input type='button' value='Generate CV' />
</div>
</Row>
</Row>
</div>
</>
)
}
export default UserDetails;
Parent component ( src -> Routes -> UserForm -> index.js )
import React from "react";
import Pages from "../../Components/HOC/Page/index";
import UserDetails from "../UserForm/Components/UserDetails/index";
class UserForm extends React.Component {
state = {
wrkExpTxtArea: [{ text: "" }],
AcQuTxtArea: [{ text: "" }],
inputValues: [{name: 'name', value: ''}],
};
inputChangeHandler = (e,inputName) => {
let updatedInputs = [...this.state.inputValues]
let changedInputValuesIndex = updatedInputs.findIndex(input => input.name === inputName)
if (changedInputValuesIndex > -1) {
let updatedInputValue =
{...updatedInputs[changedInputValuesIndex]}
updatedInputValue.value = e.target.value
updatedInputs[changedInputValuesIndex] = updatedInputValue
}
this.setState({inputValues: updatedInputs})
}
addTextArea = () => {
let updatedTextArea = [...this.state.wrkExpTxtArea];
updatedTextArea.push({ text: "" });
this.setState({ wrkExpTxtArea: updatedTextArea });
};
rmvTextArea = () => {
let updatedTextArea = [...this.state.wrkExpTxtArea];
if (updatedTextArea.length > 1) {
updatedTextArea.pop({ text: "" });
}
this.setState({ wrkExpTxtArea: updatedTextArea });
};
addAcQuTextArea = () => {
let updatedTextArea = [...this.state.AcQuTxtArea];
updatedTextArea.push({ text: "" });
this.setState({ AcQuTxtArea: updatedTextArea });
};
rmvAcQuTextArea = () => {
let updatedTextArea = [...this.state.AcQuTxtArea];
if (updatedTextArea.length > 1) {
updatedTextArea.pop({ text: "" });
}
this.setState({ AcQuTxtArea: updatedTextArea });
};
render() {
return (
<>
<Pages showHeader showFooter>
<UserDetails inputChangeHandler={this.inputChangeHandler} wrkExpTxtArea={this.state.wrkExpTxtArea} clickToAdd={this.addTextArea} clickToRmv={this.rmvTextArea}
AcQuTxtArea={this.state.AcQuTxtArea} addAcQuTxtArea={this.addAcQuTextArea} rmvAcQuTxtArea={this.rmvAcQuTextArea} />
</Pages>
</>
);
}
}
export default UserForm;
Output:
I'm new to programming and getting values of user inputs seems insanely complicated to me. I'm little aware that this can be achieved using state , props etc. But I really have no idea about Where and What code is to place. I need help. That’s it!
You can use useRef hook and give a reference to each of input element.
For Example
const name = useRef();
const handleSubmit = () => {
if(name.current && name.current.value){
console.log(name.current.value) // input element's value
}
}
return (<div>
<input type="text" ref={name} />
<button onClick={handleSubmit}> Submit </button>
</div>)
add an onChange prop to the input tag like this:
const [inputValue, setInputValue] = useState('')
const inputChangeHandler = (e) => {
// e argument has received by default from onChange
const newValue = e.target.value
setInputValue(newValue)
}
<input onChange={inputChangeHandler} />
whenever you start changing the value of the input, inputChangeHandler function will trigger and then update your state
index.js
import React, { useState } from "react";
import Pages from "../../Components/HOC/Page/index";
import UserDetails from "../UserForm/Components/UserDetails/index";
const initialData = {
name: '',
contact: '',
address: '',
facebook: '',
instagram: '',
linkedin: '',
objective: '',
workExperience: [],
academicQualification: [],
}
const UserForm = () => {
// holds all the form data from child component "UserDetails"
const [formData, setFormData] = useState(initialData)
const handleSubmit = () => {
// submit handler
alert(JSON.stringify(formData, undefined, 4))
}
return (
<>
<Pages showHeader showFooter>
<UserDetails form={formData} setter={setFormData} onSubmit={handleSubmit} />
</Pages>
</>
)
}
export default UserForm;
UserDetails
import React, { useState } from 'react'
import './style.scss';
import { Row, Col } from 'react-bootstrap'
const UserDetails = ({ form, setter, onSubmit }) => {
const hanldeOnChange = (e) => {
setter(prev => {
// access property by input element's name
// update the state on parent component
prev[e.target.name] = e.target.value;
return { ...prev } // return copy after updating
})
}
const [listTypeElements, setListTypeElements] = useState({ workExperience: '', academicQualification: '' })
const handleListInput = (property) => {
setter(prev => {
prev[property].push(listTypeElements[property]);
return { ...prev }
})
setListTypeElements(prev => {
prev[property] = ''
return { ...prev }
})
}
const handleRemoveItem = (property) => {
setter(prev => {
prev[property].pop();
return { ...prev }
})
}
return (
<>
<div className='UserDetails'>
<Row>
<Col lg='6'>
<div className='persnlInfo'>
<h4>
Personal Information
</h4>
<p>Your Name</p>
<input type="text" placeholder="Enter here" onChange={hanldeOnChange} name='name' />
<p>Your Contact</p>
<input type="text" placeholder="Enter here" onChange={hanldeOnChange} name='contact' />
<p>Your Address</p>
<textarea className='formAddress' rows="5" cols="10" placeholder="Enter here" onChange={hanldeOnChange} name='address' />
<p id='impLinks'>Important Links</p>
<p>Facebook</p>
<input type="text" placeholder="Enter here" onChange={hanldeOnChange} name='facebook' />
<p>Instagram</p>
<input type="text" placeholder="Enter here" onChange={hanldeOnChange} name='instagram' />
<p>Linkedin</p>
<input type="text" placeholder="Enter here" onChange={hanldeOnChange} name='linkedin' />
</div>
</Col>
<Col lg='6'>
<h4>
Professional Information
</h4>
<p>Objective</p>
<textarea className='formObjective' rows="5" cols="10" placeholder="Enter here" onChange={hanldeOnChange} name='objective' />
<p>Work Experience</p>
{form.workExperience.map((value) =>
<textarea className='formWrkExp' value={value} rows="3" cols="10" disabled={true} />)}
<textarea className='formWrkExp' value={listTypeElements['workExperience']} rows="3" cols="10" placeholder="Enter here" onChange={(e) => setListTypeElements(prev => {
prev['workExperience'] = e.target.value;
return { ...prev }
})} />
< div className='Button' >
<input type='button' value='Add' onClick={() => handleListInput('workExperience')} />
<input type='button' value='Remove' onClick={() => handleRemoveItem('workExperience')} />
</div>
<p id='AcQu'>Academic Qualification</p>
{form.academicQualification.map((value) =>
<textarea className='formAcQu' value={value} rows="3" cols="10" disabled={true} />)}
<textarea className='formAcQu' value={listTypeElements['academicQualification']} rows="3" cols="10" placeholder="Enter here" onChange={(e) => setListTypeElements(prev => {
prev['academicQualification'] = e.target.value;
return { ...prev }
})} />
< div className='Button' >
<input type='button' value='Add' onClick={() => handleListInput('academicQualification')} />
<input type='button' value='Remove' onClick={() => handleRemoveItem('academicQualification')} />
</div>
</Col>
<Row>
<div className='sbmtButton'>
<input type='button' value='Generate CV' onClick={onSubmit} />
</div>
</Row>
</Row>
</div>
</>
)
}
export default UserDetails;

value of the option selected not passing in react

Trying to get a response when clicking and store the selected option from the selected value genre, not sure how to add a select new state variable or a post method. When the option is clicked the click handler is not called with the selected options so that we can add it to the state. My genre is also seen as undefined when I don't click on the the text type.
Feedback.js
import React, { useState } from "react";
import axios from "axios";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.min.css";
import Layout from "./Layout";
const Feedback = () => {
const [values, setValues] = useState({
name: "",
artist: "",
songTitle: "",
email: "",
message: "",
phone: "",
genre: "",
uploadedFiles: [],
buttonText: "Submit",
uploadPhotosButtonText: "Upload files",
});
// destructure state variables
const {
name,
artist,
songTitle,
label,
email,
message,
phone,
genre,
uploadedFiles,
buttonText,
uploadPhotosButtonText,
} = values;
// destructure env variables
const {
REACT_APP_API,
REACT_APP_CLOUDINARY_CLOUD_NAME,
REACT_APP_CLOUDINARY_UPLOAD_SECRET,
} = process.env;
// event handler
const handleChange = (name) => (event) => {
setValues({ ...values, [name]: event.target.value });
};
const handleSubmit = (event) => {
event.preventDefault();
setValues({ ...values, buttonText: "...sending" });
// send to backend for email
console.table({ name, email, phone, message, uploadedFiles, genre });
axios({
method: "POST",
url: `${REACT_APP_API}/feedback`,
data: {
name,
artist,
songTitle,
label,
email,
genre,
phone,
message,
uploadedFiles,
},
})
.then((response) => {
// console.log('feedback submit response', response);
if (response.data.success) toast.success("Thanks for your feedback");
setValues({
...values,
name: "",
artist: "",
songTitle: "",
label: "",
phone: "",
email: "",
genre: "",
message: "",
uploadedFiles: [],
buttonText: "Submitted",
uploadPhotosButtonText: "Uploaded",
});
})
.catch((error) => {
// console.log('feedback submit error', error.response);
if (error.response.data.error) toast.error("Failed! Try again!");
});
};
function onChangeInput(value) {
console.log(value);
}
const uploadWidget = () => {
window.cloudinary.openUploadWidget(
{
cloud_name: REACT_APP_CLOUDINARY_CLOUD_NAME,
upload_preset: REACT_APP_CLOUDINARY_UPLOAD_SECRET,
tags: ["ebooks"],
},
function (error, result) {
// console.log(result);
setValues({
...values,
uploadedFiles: result,
uploadPhotosButtonText: `${
result ? result.length : 0
} Photos uploaded`,
});
}
);
};
const feedbackForm = () => (
<React.Fragment>
<div className="form-group">
<button
onClick={() => uploadWidget()}
className="btn btn-outline-secondary btn-block p-5"
>
{uploadPhotosButtonText}
</button>
</div>
<form onSubmit={handleSubmit}>
<div className="form-group">
<label className="text-muted">Description</label>
<textarea
onChange={handleChange("message")}
type="text"
className="form-control"
value={message}
required
></textarea>
</div>
<div className="form-group">
<label className="text-muted">Your Name</label>
<input
className="form-control"
type="text"
onChange={handleChange("name")}
value={name}
required
/>
</div>
<div className="form-group">
<label className="text-muted">Your Email</label>
<input
className="form-control"
type="email"
onChange={handleChange("email")}
value={email}
required
/>
</div>
<div className="form-group">
<label className="text-muted">Your Phone</label>
<input
className="form-control"
type="number"
onChange={handleChange("phone")}
value={phone}
required
/>
</div>
<div className="form-group">
<label className="text-muted">Artist Name</label>
<input
className="form-control"
type="text"
onChange={handleChange("artist")}
value={artist}
required
/>
</div>
<div className="form-group">
<label className="text-muted">Song Title</label>
<input
className="form-control"
type="text"
onChange={handleChange("songTitle")}
value={songTitle}
required
/>
</div>
<div className="form-group">
<label className="text-muted">Record Label Name</label>
<input
className="form-control"
type="text"
onChange={handleChange("label")}
value={label}
/>
</div>
<div className="form-group">
<label className="text-muted">Music Genre:</label>
<select
className="form-control"
value={genre}
type="select"
onChange={handleChange("genre")}
>
<option value="steak">Steak</option>
<option value="sandwich">Sandwich</option>
<option value="dumpling">Dumpling</option>
</select>
</div>
<button className="btn btn-outline-primary btn-block">
{buttonText}
</button>
</form>
</React.Fragment>
);
return (
<Layout>
<ToastContainer />
<div className="container text-center">
<h1 className="p-5">Feedback Online</h1>
</div>
<div className="container col-md-8 offset-md-2">{feedbackForm()}</div>
<br />
<br />
<br />
</Layout>
);
};
export default Feedback;

Resources