How can I persist updated form data after submit? - javascript

So I have some formdata in my react app that I want to persist after I make a put request to the mongodb. Problem is that the change is not visible on page refresh. It is only after I log out and log in again that I can see the updated value in the form.
For example let's say that I want to change my first name from John to Eric. The change will update but not in the form. In the form the value will still be John until I log out and in again.
It feels almost like it has to do with the jwt token but I don't know. Any ideas what the problem can be?
export const Edit = () => {
const navigate = useNavigate();
const user = Cookies.get("access_token");
const [id, setId] = useState(null)
const [firstName, setFirstName] = useState("")
const [lastName, setLastName] = useState("")
const [city, setCity] = useState("")
const [email, setEmail] = useState("")
const checkUser = async () => {
try {
const res = await axios
.get(`${process.env.REACT_APP_API_URL}user/protected`, {
withCredentials: true,
headers: {
Authorization: `Bearer ${user}`,
},
})
console.log(res.data.user);
setId(res.data.user.id)
setFirstName(res.data.user.firstName)
setLastName(res.data.user.lastName)
setCity(res.data.user.city)
setEmail(res.data.user.email)
} catch (error) {
console.warn(error)
}
}
useEffect(() => {
if (!user) {
navigate('/')
} else {
checkUser();
}
}, []);
const updateUser = async () => {
try {
const userData = {
firstName: firstName,
lastName: lastName,
city: city,
email: email
}
const API_URL = `${process.env.REACT_APP_API_URL}user/`;
const userId = id;
const res = await axios.put(API_URL + "/" + userId + "/edit", userData)
setFirstName(res.data.firstName)
setLastName(res.data.lastName)
setCity(res.data.city)
setEmail(res.data.email)
// works and is updated in the database
} catch (error) {
console.warn(error)
}
}
return (
<>
<section className="m-5">
<h1 className="mb-5 text-center">Settings</h1>
<form className="row g-3">
<div className="col-md-6">
<label htmlFor="firstName" className="form-label">
First name
</label>
<p>{formErrors.firstName}</p>
<input
type="text"
className="form-control"
id="firstName"
name="firstName"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
</div>
<div className="col-md-6">
<label htmlFor="lastName" className="form-label">
Last name
</label>
<p>{formErrors.lastName}</p>
<input
type="text"
className="form-control"
id="lastName"
name="lastName"
value={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
</div>
<div className="col-md-6">
<label htmlFor="city" className="form-label">
City
</label>
<p>{formErrors.city}</p>
<input
type="text"
className="form-control"
id="city"
name="city"
value={city}
onChange={(e) => setCity(e.target.value)}
/>
</div>
<div className="col-md-6">
<label htmlFor="email" className="form-label">
Email
</label>
<p>{formErrors.email}</p>
<input
type="email"
className="form-control"
id="email"
name="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="col-12 pt-4 text-center">
<button
type="submit"
className="btn btn-primary btn-lg"
onClick={updateUser}
>
Update
</button>
</div>
<div className="col-12 pt-1 text-center">
<button
type="submit"
className="btn btn btn-lg"
>
<a href="edit/password" className="text-decoration-none">
Change Password
</a>
</button>
</div>
</form>
</section>
</>
);
};

Add user as a dependency to the useEffect's dependency array:
useEffect(() => {
if (!user) {
navigate('/')
} else {
checkUser();
}
}, [user]);

Related

FirebaseError: Firebase: Error (auth/invalid-email)

I am making a react project and when I am trying to sign up through email and password using firebase authentication then this 👇your text error is showing
This is the error I am getting
This is the whole code:
import React,{useState} from 'react';
import { Link, useNavigate } from 'react-router-dom';
import Layout from '../components/layout/Layout';
import {BsFillEyeFill} from "react-icons/bs";
import { getAuth, createUserWithEmailAndPassword , updateProfile} from "firebase/auth";
import {db} from "../firebase.config"
const SignUp = () => {
// to hide password
const [showPassword, setShowPassword] = useState(false);
const [formData, setFormData] = useState({
email:"",
name: "",
password: "",
})
const {name, email, password} = formData;
const navigate = useNavigate();
const onChange = (e) => {
setFormData((prevState) => ({
...prevState,
[e.target.id]: e.target.value,
}));
};
This is my signUp function
const onSubmitHandler= async (e) =>{
e.preventDefault();
try{
const auth= getAuth()
const userCredential = await createUserWithEmailAndPassword(auth,email,password);
const user = userCredential.user
updateProfile(auth.currentUser,{displayName: name})
navigate("/")
alert("Signup Success")
}catch(error){
console.log(error);
}
}
return (
<Layout>
<div className="d-flex align-items-center justify-content-center w-100 mt-5 mb-5">
<form className='bg-light p-4 rounded-3 border border-dark border-3' onSubmit={onSubmitHandler}>
<h4 className='bg-dark p-2 mt-2 text-light rounded-2 text-center'>Sign Up</h4>
<div className="mb-3">
<label htmlFor="exampleInputEmail1" className="form-label">Enter Name</label>
<input
type="text"
defaultValue={name}
id="name"
onChange={onChange}
className="form-control"
aria-describedby="nameHelp"
/>
</div>
<div className="mb-3">
<label htmlFor="exampleInputEmail1" className="form-label">Email address</label>
<input
type="email"
defaultValue={email}
onChange={onchange}
className="form-control"
id="email"
aria-describedby="emailHelp"
/>
<div id="emailHelp" className="form-text">We'll never share your email with anyone else.</div>
</div>
<div className="mb-3">
<label htmlFor="exampleInputPassword1" className="form-label">Password</label>
<input
type={showPassword? "text" : "password"}
defaultValue={password}
onChange={onchange}
className="form-control"
id="password"
/>
<span >Show Password <BsFillEyeFill
className='text-primary ms-2'
style={{cursor: "pointer"}}
onClick={()=> setShowPassword((prevState)=> !prevState)}
/></span>
</div>
<button
type="submit"
className="btn btn-primary">Sign Up</button>
<div>
<h6>Login with Google</h6>
<span>Already User?</span> <Link to="/signin">Login</Link>
</div>
</form>
</div>
</Layout>
)
}
export default SignUp
After going through firebase documentation I have tried various emails but still it is showing the same error.
This is the email I had been using for signUp.
and I tried different emails as well like: piyush#gmail.com, and my personal email too but still it is showing the same error
This is the error message for your error
auth/invalid-email:
The provided value for the email user property is invalid. It must be a string email address.
Check to make sure your onSubmitHandler is within scope of your formData state, because your email and password might be undefined.
Your code has 2 issues,
1: Check the spelling of onChange on email and password field.
2: Change defaultValue to value
Below is the working code:
import React, { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { BsFillEyeFill } from 'react-icons/bs';
import {
getAuth,
createUserWithEmailAndPassword,
updateProfile,
} from 'firebase/auth';
const Signup = () => {
const [showPassword, setShowPassword] = useState(false);
const [formData, setFormData] = useState({
email: '',
name: '',
password: '',
});
const { name, email, password } = formData;
const navigate = useNavigate();
const onChange = (e: any) => {
setFormData((prevState) => ({
...prevState,
[e.target.id]: e.target.value,
}));
};
const onSubmitHandler = async (e) => {
e.preventDefault();
console.log('email is ', email, password);
try {
const auth = getAuth();
const userCredential = await createUserWithEmailAndPassword(
auth,
email,
password,
);
const user = userCredential.user;
alert('Signup Success');
} catch (error) {
console.log(error);
}
};
return (
<div className="d-flex align-items-center justify-content-center w-100 mt-5 mb-5">
<form
className="bg-light p-4 rounded-3 border border-dark border-3"
onSubmit={onSubmitHandler}
>
<h4 className="bg-dark p-2 mt-2 text-light rounded-2 text-center">
Sign Up
</h4>
<div className="mb-3">
<label htmlFor="exampleInputEmail1" className="form-label">
Enter Name
</label>
<input
type="text"
value={name}
id="name"
onChange={onChange}
className="form-control"
aria-describedby="nameHelp"
/>
</div>
<div className="mb-3">
<label htmlFor="exampleInputEmail1" className="form-label">
Email address
</label>
<input
type="email"
value={email}
onChange={onChange}
className="form-control"
id="email"
aria-describedby="emailHelp"
/>
<div id="emailHelp" className="form-text">
We'll never share your email with anyone else.
</div>
</div>
<div className="mb-3">
<label htmlFor="exampleInputPassword1" className="form-label">
Password
</label>
<input
type={showPassword ? 'text' : 'password'}
value={password}
onChange={onChange}
className="form-control"
id="password"
/>
<span>
Show Password{' '}
<BsFillEyeFill
className="text-primary ms-2"
style={{ cursor: 'pointer' }}
onClick={() => setShowPassword((prevState) => !prevState)}
/>
</span>
</div>
<button type="submit" className="btn btn-primary">
Sign Up
</button>
<div>
<h6>Login with Google</h6>
<span>Already User?</span> <Link to="/signin">Login</Link>
</div>
</form>
</div>
);
};
export default Signup;

Not able to submit the data to firebase from contact form

import React, { useState } from 'react'
import styled from 'styled-components'
import Title from '../Components/Title'
import { InnerLayout, MainLayout } from '../Styles/Layout'
import Button from '../Components/Button'
import { db } from '../firebase';
function Contact() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [message, setMessage] = useState("");
const [subject, setSubject] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
db.collection('mail').add({
name: name,
email: email,
subject: subject,
message: message,
})
.then(() => {
alert("Thank you for contacting. Your message has been sent successfully.");
})
.catch((err) => {
alert(err.message);
});
setName('')
setEmail('')
setSubject('')
setMessage('')
};
return (
<MainLayout>
<Title title={'Contact'} span={'Contact'} />
<ContactMain>
<InnerLayout className='contact-section'>
<div className="left-content">
<div className="contact-title">
<h4>Get In Touch</h4>
</div>
<form className="form" onSubmit={handleSubmit}>
<div className="form-field">
<label htmlFor="name">Enter Your Name</label>
<input type="text" id="name" value={name} onChange={(e) => setName(e.target.value)} />
</div>
<div className="form-field">
<label htmlFor="email">Enter Your Email</label>
<input type="email" id="email" value={email} onChange={(e) => setEmail(e.target.value)} />
</div>
<div className="form-field">
<label htmlFor="subject">Enter Your Subject</label>
<input type="text" id="subject" value={subject} onChange={(e) => setSubject(e.target.value)} />
</div>
<div className="form-field">
<label htmlFor="text-area">Enter Your Message</label>
<textarea name="textarea" id="textarea" cols="30" rows="10" value={message} onChange={(e) => setMessage(e.target.value)}></textarea>
</div>
<div className="form-field f-button">
<Button title="Send Email" />
</div>
</form>
</div>
</InnerLayout>
</ContactMain>
</MainLayout>
)
}
I don't know why but I am not able to send the details to my firebase database. I am not able to find the issue in this code. I have copied the firebase database key and all in the firebase.js and then imported it in this contact.js and I then made the necessary changes in this. Still, I am not able to figure out the issue.
I would reset the form once the promise returned by add() is resolved.
const handleSubmit = (e) => {
e.preventDefault();
db.collection('mail').add({
name: name,
email: email,
subject: subject,
message: message,
}).then(() => {
// Reset those states here
setName('')
setEmail('')
setSubject('')
setMessage('')
alert("Thank you for contacting. Your message has been sent successfully.");
}).catch((err) => {
alert(err.message);
});
};
I guess your states are being reset to "" before the document is added as those setState methods would have ran before the doc was added.
Potentially because your button html within its the button component type is not set to 'submit' - I had the same issue I think which ended up being super simple.

Problems with Registering User

So, I have a backend auth which is showing me the Userdata in the postman and as well in the Mongo. I had an error in the console xhr.js:177 POST http://localhost:3000/api/auth/register 404 (Not Found) which I think I fixed by adding ""http://localhost:5000/api/auth/register", instead of just api/auth/register in the post method, but now when I try to register I am getting this error Unhandled Rejection (TypeError): Cannot read property 'data' of undefined. If someone would tell me why is this showing, and how to I fix it, I would be grateful. Thanks
import axios from "axios";
import { Link } from "react-router-dom";
const Register = ({ history }) => {
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmpassword, setConfirmPassword] = useState("");
const [error, setError] = useState("");
const registerHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
if (password !== confirmpassword) {
setPassword("");
setConfirmPassword("");
setTimeout(() => {
setError("");
}, 5000);
return setError("Passwords do not match");
}
try {
const { data } = await axios.post(
"http://localhost:5000/api/auth/register",
{
username,
email,
password,
},
config
);
localStorage.setItem("authToken", data.token);
history.push("/");
} catch (error) {
setError(error.response.data.error);
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="register-screen">
<form onSubmit={registerHandler} className="register-screen__form">
<h3 className="register-screen__title">Register</h3>
{error && <span className="error-message">{error}</span>}
<div className="form-group">
<label htmlFor="name">Username:</label>
<input
type="text"
required
id="name"
placeholder="Enter username"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
<div className="form-group">
<label htmlFor="email">Email:</label>
<input
type="email"
required
id="email"
placeholder="Email address"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="form-group">
<label htmlFor="password">Password:</label>
<input
type="password"
required
id="password"
autoComplete="true"
placeholder="Enter password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div className="form-group">
<label htmlFor="confirmpassword">Confirm Password:</label>
<input
type="password"
required
id="confirmpassword"
autoComplete="true"
placeholder="Confirm password"
value={confirmpassword}
onChange={(e) => setConfirmPassword(e.target.value)}
/>
</div>
<button type="submit" className="btn btn-primary">
Register
</button>
<span className="register-screen__subtext">
Already have an account? <Link to="/login">Login</Link>
</span>
</form>
</div>
);
};
export default Register;
you need to check for error.response existence. Seems like it is undefined in your case.
if (error.response) {
setError(error.response.data.error);
}
setTimeout(() => {
setError("");
}, 5000);
That will help you with this error Cannot read property 'data' of undefined but to answer why you're getting xhr.js:177 POST http://localhost:3000/api/auth/register 404 (Not Found) we need more information. Simply there is no /api/auth/register handler on your server.

Form edit not working in react with onchange

I am trying to populate a form with data from different tables and allow the user to update the data for both.
I have populated the data in the form but I am not able to edit the data for certain fields which I have called inside a map function.
It is not allowing me to change or add data. Refer last input element of the form.
import React, { Fragment, useState, useEffect } from "react";
const ViewPt = ({ pts }) => {
// const [description, setDescription] = useState(todo.description);
const [name, setName] = useState(pts.name);
const [mobile, setMobile] = useState(pts.mobile);
const [email, setEmail] = useState(pts.email);
const [gender, setGender] = useState(pts.gender);
const [dob, setDob] = useState(pts.dob);
const [address, setAddress] = useState(pts.address);
const [treatment, setTreatment] = useState([]);
const [treatment_date, setTreatment_date] = useState("");
const [treatment_done, setTreatment_done] = useState("");
const [cost, setCost] = useState("");
const [paid, setPaid] = useState("");
const [next_appointment, setNext_appointment] = useState("");
const [selectedTreatment, setSelectedTreatment] = useState(false);
//edit patient function
const updatePatient = async(e) => {
e.preventDefault();
try {
const body ={ name,email,mobile,gender,dob,address };
const response = await fetch(`http://localhost:5000/patients/${pts.patient_id}`,{
method: "PUT",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(body)
});
window.location ="/";
} catch (err) {
console.error(err.message);
}
}
//get treatment information
const getTreatment = async() =>{
try {
const response = await fetch(`http://localhost:5000/patients/:id/treatment`)
const jsonData = await response.json();
setTreatment(jsonData);
} catch (err) {
console.error(err.message);
}
}
useEffect(() => {
getTreatment();
},[]);
//function for getting treatment details
const filterTreatmentDetails =async(e) =>{
console.log("__here__1", pts, treatment);
try{
const filtered = treatment.filter(t => pts.patient_id == t.patient_id);
if (
filtered
&& filtered.length > 0
) {
setSelectedTreatment(filtered);
}
console.log(filtered);
console.log("__here__2");
return filtered;
}
catch (err) {
console.error(err.message);
}
}
//edit treatment function
const updateTreatment = async(e) => {
e.preventDefault();
try {
const body ={ treatment_date,treatment_done,cost,paid,next_appointment };
const response = await fetch(`http://localhost:5000/patients/${pts.patient_id}/treatment`,{
method: "PUT",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(body)
});
window.location ="/";
} catch (err) {
console.error(err.message);
}
}
return <Fragment>
<button type="button" class="btn btn-warning" data-toggle="modal" onClick={filterTreatmentDetails} data-target={`#view${pts.patient_id}`}>
Edit
</button>
<div class="modal" id={`view${pts.patient_id}`}>
{/* onClick={() => setDescription(todo.description)} */}
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Edit Data</h4>
<button type="button" class="close" data-dismiss="modal" >×</button>
</div>
<form className="text-left" onSubmit={updatePatient,updateTreatment}>
<div class="modal-body">
<div class="form-control">
<label for="name">Name </label>
<input type="text" className="form-control" id="name" placeholder="Enter Name" value={name} onChange={e=>setName(e.target.value)}/>
<small></small>
</div>
<div class="form-control" >
<label for="gender">Gender </label>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" id="inlineRadio1" value={gender} onChange ={e =>setGender(`m`)} />
<label class="form-check-label" for="inlineRadio1">Male</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" id="inlineRadio2" value={gender} onChange ={e =>setGender(`f`)} />
<label class="form-check-label" for="inlineRadio2">Female</label>
</div>
<small></small>
</div>
<div class="form-control">
<label for="email">Email</label>
<input type="text" className="form-control" id="email" placeholder="Enter Email" value={email} onChange={e=>setEmail(e.target.value)} />
<small></small>
</div>
<div class="form-control">
<label for="mobile">mobile</label>
<input type="number" className="form-control" id="mobile" placeholder="Enter 10 digit number" value={mobile} onChange={e=>setMobile(e.target.value)}/>
<small></small>
</div>
<div class="form-control">
<label for="dob">Date of Birth</label>
<input type="text" className="form-control" id="dob" placeholder="dob" value={dob}/>
<input type="date" className="form-control" id="dob" placeholder="dob" value={dob} onChange={e=>setDob(e.target.value)}/>
<small></small>
</div>
<div class="form-control">
<label for="address">Address</label>
<input type="text" className="form-control" id="address" placeholder="address" value={address} onChange={e=>setAddress(e.target.value)}/>
<small></small>
</div>
{
selectedTreatment && selectedTreatment.map(subTreatment => (
<div class="form-control" key={subTreatment.treatment_id}>
<label for="treatment">Treatment Done</label>
<input
type="text"
className="form-control"
id="treatment"
placeholder="Treatment Done"
value={subTreatment.treatment_done}
onChange={e=>setTreatment_done(e.target.value)}
/>
<small></small>
</div>
))
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-warning" data-dismiss="modal" onClick = {e => {updatePatient(e);updateTreatment(e)}}>Edit</button>
{/* <button type="button" class="btn btn-danger" data-dismiss="modal" onClick={() => {setName(patient.name),setEmail(patient.email),setMobile(patient.mobile),setGender(patient.gender),setDob(patient.dob),setAddress(patient.address)}}>Close</button> */}
</div>
</form>
</div>
</div>
</div>
</Fragment>
};
export default ViewPt;
In my understanding, below code is not working :
onChange={e=>setTreatment_done(e.target.value)}
I really appreciate your help!
In your hook, you are using treatment_done
const [treatment_done, setTreatment_done] = useState("");
but in your last input, the value is using
subTreatment.treatment_done, so
treatment_done
in your state hook has never been used.

How to update state after a promise response in react.js

I have class component for user sign up along with a form. I am making an api call based on user input to check if a user exists. The handleInputChange initially sets the state to some user input and the handleSubmit makes a call to another function which fetches from an endpoint. I want to set this.state.user to that response. I tried what was on this link but couldn't get it to work. Any ideas would help
import React, { Component } from 'react';
const user_add_api = "http://localhost:5000/add_user";
const user_check_api = "http://localhost:5000/user_by_username/";
here is the class:
class SignUp extends Component {
constructor(props) {
super(props);
this.state = {
first_name: '',
last_name: '',
username: '',
email: '',
password: '',
user: ''
};
}
checkUser = (user) => {
const userPromise = fetch(user_check_api + user);
var meh = '123meh';
userPromise
.then(data => data.json())
.then(data => this.setState({user: {...this.state.user, meh}}))
// let curr = {...this.state};
// curr['user'] = 'somevalue';
// this.setState({ curr:curr['user'] });
console.log(this.state.user);
}
handleSubmit = (event) => {
event.preventDefault();
const data = this.state;
let s = this.checkUser(data.username);
console.log(data);
}
handleInputChange = (event) => {
event.preventDefault();
this.setState({
[event.target.name]: event.target.value,
})
}
render () {
return (
<form className="form-horizontal">
<div className="form-group">
<label className="col-md-4 control-label">First Name</label>
<div className="col-md-4">
<input name="first_name" type="text" placeholder="John" className="form-control input-md" required onChange={this.handleInputChange}></input>
</div>
<label className="col-md-4 control-label">Last Name</label>
<div className="col-md-4">
<input name="last_name" type="text" placeholder="Doe" className="form-control input-md" required onChange={this.handleInputChange}></input>
</div>
<label className="col-md-4 control-label">Username</label>
<div className="col-md-4">
<input name="username" type="text" placeholder="John Doe" className="form-control input-md" required onChange={this.handleInputChange}></input>
</div>
<label className="col-md-4 control-label">Email</label>
<div className="col-md-4">
<input name="email" type="text" placeholder="johndoe#example.com" className="form-control input-md" required onChange={this.handleInputChange}></input>
</div>
<label className="col-md-4 control-label">Password</label>
<div className="col-md-4">
<input name="password" type="password" placeholder="" className="form-control input-md" required onChange={this.handleInputChange}></input>
</div>
<label className="col-md-4 control-label"></label>
<div className="col-md-8">
<button name="save" onClick={this.handleSubmit} className="btn btn-success">Register</button>
</div>
</div>
</form>
);
}
}
export default SignUp;
This fetch(user_check_api + user) return a Promise and you not wait it. Maybe you should change like that
checkUser = (user) => {
var meh = '123meh';
fetch(user_check_api + user)
.then(data => data.json())
.then(data => {
this.setState({user: {...this.state.user, meh}})
console.log(this.state.user) // Show log in in success func
})
}
Or use async/await
checkUser = async (user) => {
const userPromise = await fetch(user_check_api + user);
var meh = '123meh';
userPromise
.then(data => data.json())
.then(data => this.setState({
user: {...this.state.user, meh}
}, console.log(this.state.user))) // Show log in callback
}

Categories

Resources