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

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
}

Related

How can I persist updated form data after submit?

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]);

Resetting React Form values after validation

have that problem with resetting the values of the input fields in the form. and wanted to ask if somebody knows a better and way to do that instead of just making 'useState' for every field...
const handleSubmit = (e) => {
e.preventDefault();
emailjs.sendForm('sample_id', 'someother_id', formRef.current, 'user_is')
.then((result) => {
console.log(result.text);
}, (error) => {
console.log(error.text);
});
setMessage(true);
setEmail("");
setName("");
setSubject("");
setTextarea("");
};
return (
<div className="contact" id="contact">
<div className="left">
<img src="" alt="" />
</div>
<div className="right">
<h2>Kontakt</h2>
<form ref={formRef} onSubmit={handleSubmit}>
<label>Name</label>
<input onChange={(e) => setName(e.target.value)} type="text" placeholder="Name" name="user_name" value={name} />
<label>Email</label>
<input onChange={(e) => setEmail(e.target.value)} type="email" placeholder="Email" name="user_email" value={email} />
<label>Betreff</label>
<input onChange={(e) => setSubject(e.target.value)} type="text" placeholder="Subject" name="user_subject" value={subject} />
<label>Nachricht</label>
<textarea onChange={(e) => setTextarea(e.target.value)} placeholder="Message" name="message" value={textarea} />
<button type="submit">Send</button>
{message && <span>Thanks we will respond ASAP.</span>}
</form>
</div>
</div>
)
}
You could use a single state for all the form values (kinda like we did before functional components)
// this could be outside your component
const initialState = { email: "", name: "", subject: "", textArea: ""};
// declaring your state
const [formState, setFormState] = React.useState(initialState);
and then
const handleSubmit = (e) => {
e.preventDefault();
emailjs.sendForm('sample_id', 'someother_id', formRef.current, 'user_is')
.then((result) => {
console.log(result.text);
}, (error) => {
console.log(error.text);
});
setMessage(true);
setFormState(initialState)
};
You also would have to rewrite your input handlers. Like that :
<input onChange={(e) => setFormState({...formState, name: e.target.value})} type="text" placeholder="Name" name="user_name" value={name} />

React Form values are not reflected on the FORM items for EDIT using class state

I'm pulling data from MongoDB and trying to edit the data but for some reason, my form is not showing the values on the form. Can anyone help to guide me on what I am getting wrong? below is my code for any help why form value are not updated using this.state.job_title as an example:
edit-job.component.js
import React, { Component } from "react";
import axios from "axios";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
export default class EditJob extends Component {
constructor(props) {
super(props);
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onChangeJob_title = this.onChangeJob_title.bind(this);
this.onChangejob_comp_image = this.onChangejob_comp_image.bind(this);
this.onChangejob_comp_name = this.onChangejob_comp_name.bind(this);
this.onChangejob_description = this.onChangejob_description.bind(this);
this.onChangejob_location = this.onChangejob_location.bind(this);
this.onChangejob_field = this.onChangejob_field.bind(this);
this.onChangeDatejob_closing_date =
this.onChangeDatejob_closing_date.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
username: "",
job_title: "",
job_comp_image: "",
job_comp_name: "",
job_description: "",
job_location: "",
job_field: "",
job_closing_date: new Date(),
users: [],
};
}
componentDidMount() {
//GET CURRENT JOB LISTING TO EDIT
if (this.props.match && this.props.match.params.id) {
axios
.get("http://localhost:5001/jobs/" + this.props.match.params.id)
.then((response) => {
console.log(response.data);
this.setState({
username: response.data.username,
job_title: response.data.job_title,
job_comp_image: response.data.job_comp_image,
job_comp_name: response.data.job_comp_name,
job_description: response.data.job_description,
job_location: response.data.job_location,
job_field: response.data.job_field,
job_closing_date: new Date(response.data.job_closing_date),
});
})
.catch(function (error) {
console.log(error);
});
}
axios
.get("http://localhost:5001/users/")
.then((response) => {
if (response.data.length > 0) {
this.setState({
users: response.data.map((user) => user.username),
});
}
})
.catch((error) => {
console.log(error);
});
}
onChangeUsername(e) {
this.setState({
username: e.target.value,
});
}
//Update user with new username entered by user
onChangeJob_title(e) {
this.setState({
job_title: e.target.value,
});
}
onChangejob_comp_image(e) {
this.setState({
job_comp_image: e.target.value,
});
}
onChangejob_comp_name(e) {
this.setState({
job_comp_name: e.target.value,
});
}
onChangejob_description(e) {
this.setState({
job_description: e.target.value,
});
}
onChangejob_location(e) {
this.setState({
job_location: e.target.value,
});
}
onChangejob_field(e) {
this.setState({
job_field: e.target.value,
});
}
onChangeDatejob_closing_date(job_closing_date) {
this.setState({
job_closing_date: job_closing_date,
});
}
onSubmit(e) {
e.preventDefault();
const job = {
username: this.state.username,
job_title: this.state.username,
job_comp_image: this.state.job_comp_image,
job_comp_name: this.state.job_comp_name,
job_description: this.state.job_description,
job_location: this.state.job_location,
job_field: this.state.job_field,
job_closing_date: new Date(),
};
console.log(job);
axios
.post(
"http://localhost:5001/jobs/update/" + this.props.match.params.id,
job
)
.then((res) => console.log(res.data));
window.location = "/";
}
render() {
const Headerstyle = {
marginTop: "40px",
};
return (
<div style={Headerstyle}>
<h3>Edit Exercise Log</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username: </label>
<select
UseRef="userInput"
required
className="form-control"
value={this.state.username}
onChange={this.onChangeUsername}
>
{this.state.users.map(function (user) {
return (
<option key={user} value={user}>
{user}
</option>
);
})}
</select>
</div>
<div className="form-group">
<label>Job Title: </label>
<input
type="text"
required
className="form-control"
value={this.state.job_title}
onChange={this.onChangeJob_title}
/>
</div>
<div className="form-group">
<label>Company Image: </label>
<input
type="text"
className="form-control"
value={this.state.job_comp_image}
onChange={this.onChangejob_comp_image}
/>
</div>
<div className="form-group">
<label>Company Name: </label>
<input
type="text"
className="form-control"
value={this.state.job_comp_name}
onChange={this.onChangejob_comp_name}
/>
</div>
<div className="form-group">
<label>Job Description: </label>
<input
type="text"
className="form-control"
value={this.state.job_description}
onChange={this.onChangejob_description}
/>
</div>
<div className="form-group">
<label>Job Location: </label>
<input
type="text"
className="form-control"
value={this.state.job_location}
onChange={this.onChangejob_location}
/>
</div>
<div className="form-group">
<label>Job related field: </label>
<input
type="text"
className="form-control"
value={this.state.job_field}
onChange={this.onChangejob_field}
/>
</div>
<div className="form-group">
<label>Job Closing Date: </label>
<div>
<DatePicker
selected={this.state.job_closing_date}
onChange={this.onChangeDatejob_closing_date}
/>
</div>
</div>
<div className="form-group">
<input
type="submit"
value="Edit Job Listing"
className="btn btn-primary"
/>
</div>
</form>
</div>
);
}
}

React Hooks, object state is not updating onSubmit

I am using React Hooks and am created a form to submit blog posts. I am having trouble writing the submitPost logic. I have a post, and setPost variable. setPost doesn't seem to be updating post with the new post in the submitPost function, so my api call function createPost isn't receiving the new req.body. But when I created a second function changePost(), post is updated.
This is my code.
export default function NewPost({ props }) {
const [post, setPost] = useState({
title: "",
img: "",
content: "",
user_id: 0,
});
const [img, setImg] = useState("");
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [userId, setUserId] = useState(0);
useEffect(() => {
const handleUser = async () => {
try {
const response = await verifyUser();
console.log(response);
setUserId(response.user.id);
} catch (error) {
console.log(error);
}
};
handleUser();
});
const changePost = () => {
const newPost = {
title: title,
img: img,
content: content,
user_id: userId,
};
setPost(newPost);
console.log(post);
};
const submitPost = async (e) => {
e.preventDefault();
console.log(userId);
try {
console.log(title);
changePost();
console.log("submitPost", post);
await createPost(post);
props.history.push("/posts");
} catch (error) {
console.log(error);
}
};
console.log(post);
return (
<div>
<Nav />
<div class="ui main text container segment mt-100">
<div class="ui huge header salmon">New Blog </div>
<form class="ui form" onSubmit={submitPost}>
<div class="field">
<label> Title </label>
<input
type="text"
name="title"
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="title"
/>
</div>
<div class="field">
<label> Image </label>
<input
type="text"
name="img"
value={img}
onChange={(e) => setImg(e.target.value)}
placeholder="image"
/>
</div>
<div class="field">
<label> Body </label>
<textarea
name="content"
value={content}
onChange={(e) => setContent(e.target.value)}
placeholder="blog post goes here"
>
{" "}
</textarea>
</div>
<input class="ui teal big basic button" type="submit" />
</form>
</div>
</div>
);
}
It won't work. You're trying to create a post where your post variable is not yet updated. You don't need to create so many variables, just use the post variable.
Try using the below code.
export default function NewPost({ props }) {
const [post, setPost] = useState({
title: "",
img: "",
content: "",
user_id: 0,
});
useEffect(() => {
const handleUser = async () => {
try {
const response = await verifyUser();
console.log(response);
setPost({...post, user_id: response.user.id});
} catch (error) {
console.log(error);
}
};
handleUser();
});
const submitPost = async (e) => {
e.preventDefault();
console.log(userId);
try {
console.log(title);
console.log("submitPost", post);
await createPost(post);
props.history.push("/posts");
} catch (error) {
console.log(error);
}
};
console.log(post);
return (
<div>
<Nav />
<div class="ui main text container segment mt-100">
<div class="ui huge header salmon">New Blog </div>
<form class="ui form" onSubmit={submitPost}>
<div class="field">
<label> Title </label>
<input
type="text"
name="title"
value={title}
onChange={(e) => setPost({...post, title: e.target.value})}
placeholder="title"
/>
</div>
<div class="field">
<label> Image </label>
<input
type="text"
name="img"
value={img}
onChange={(e) => setPost({...post, img: e.target.value})}
placeholder="image"
/>
</div>
<div class="field">
<label> Body </label>
<textarea
name="content"
value={content}
onChange={(e) => setPost({...post, content: e.target.value})}
placeholder="blog post goes here"
>
{" "}
</textarea>
</div>
<input class="ui teal big basic button" type="submit" />
</form>
</div>
</div>
);
}
just do this .
useEffect(()=>{
},[JSON.stringify(post)])..
setPost({ title,img,content,user_id});

How to add select option data into the server using react js

I am currently working on an e-commerce project using react js. There is a problem of saving/adding user data especially gender( select option). Anyone help to solve this problem.
I use react-select as the component in user from as:
User_form:
This is our user form component that is used for creating users.
import React, { Component, Fragment } from "react";
import { Tabs, TabList, TabPanel, Tab } from "react-tabs";
import PropTypes from "prop-types";
import { register } from "../../redux/actions/auth";
import { createMessage } from "../../redux/actions/message";
import { connect } from "react-redux";
import Select from "react-select";
export class Tabset_user extends Component {
state = {
first_name: "",
last_name: "",
username: "",
email: "",
password: "",
password2: "",
gender: [],
};
static propTypes = {
register: PropTypes.func.isRequired,
isAuthenticated: PropTypes.bool,
};
onSubmit = (e) => {
e.preventDefault();
const {
first_name,
last_name,
username,
email,
password,
password2,
phone,
gender,
} = this.state;
if (password !== password2) {
// this.props.createMessage({ passwordNotMatch: "Passwords do not match" });
alert("Password don't match");
} else {
const newUser = {
first_name,
last_name,
username,
password,
email,
phone,
gender,
};
this.props.register(newUser);
}
};
onChange = (e) => this.setState({ [e.target.name]: e.target.value });
handleChange = (value) => {
this.setState({ gender: value });
};
render() {
const options = [
{ value: "Male", label: "Male" },
{ value: "Female", label: "Female" },
{ value: "Perfer Not To Say", label: "Perfer Not to Say" },
];
const {
first_name,
last_name,
username,
email,
password,
password2,
phone,
} = this.state;
return (
<Fragment>
<Tabs>
<TabList className="nav nav-tabs tab-coupon">
<Tab className="nav-link">Account</Tab>
<Tab className="nav-link">Permission</Tab>
</TabList>
<TabPanel>
<form
className="needs-validation user-add"
onSubmit={this.onSubmit}
>
<h4>Account Details</h4>
<div className="form-group row">
<label className="col-xl-3 col-md-4">First Name</label>
<input
className="form-control col-xl-8 col-md-7"
id="first_name"
type="text"
name="first_name"
value={first_name}
onChange={this.onChange}
placeholder="First Name"
/>
</div>
<div className="form-group row">
<label className="col-xl-3 col-md-4">Last Name</label>
<input
className="form-control col-xl-8 col-md-7"
id="validationCustom1"
type="text"
name="last_name"
value={last_name}
onChange={this.onChange}
placeholder="Last Name"
/>
</div>
<div className="form-group row">
<label className="col-xl-3 col-md-4">
<span>*</span> Email
</label>
<input
className="form-control col-xl-8 col-md-7"
id="email"
type="email"
name="email"
value={email}
onChange={this.onChange}
placeholder="Email Address"
/>
</div>
<div className="form-group row">
<label className="col-xl-3 col-md-4">
<span>*</span> Username
</label>
<input
className="form-control col-xl-8 col-md-7"
id="username"
type="text"
name="username"
value={username}
onChange={this.onChange}
placeholder="Username"
/>
</div>
<div className="form-group row">
<label className="col-xl-3 col-md-4">
<span>*</span> Password
</label>
<input
className="form-control col-xl-8 col-md-7"
id="validationCustom3"
type="password"
name="password"
value={password}
onChange={this.onChange}
placeholder="Password"
/>
</div>
<div className="form-group row">
<label className="col-xl-3 col-md-4">
<span>*</span> Confirm Password
</label>
<input
className="form-control col-xl-8 col-md-7"
id="validationCustom4"
type="password"
name="password2"
value={password2}
onChange={this.onChange}
placeholder="Confirm Password"
/>
</div>
<div className="form-group row">
<label className="col-xl-3 col-md-4">Gender</label>
<Select
className="form-control col-xl-8 col-md-7"
options={options}
value={this.state.gender}
onChange={this.handleChange}
name="gender"
/>
</div>
<div className="form-group row">
<label className="col-xl-3 col-md-4">Phone</label>
<input
className="form-control col-xl-8 col-md-7"
id="phone"
type="number"
name="phone"
value={phone}
onChange={this.onChange}
placeholder="Phone Number"
/>
</div>
<div className="pull-right">
<button type="submit" className="btn btn-primary">
Save
</button>
</div>
</form>
</TabPanel>
</Tabs>
</Fragment>
);
}
}
const mapStateToProps = (state) => ({
isAuthenticated: state.auth.isAuthenticated,
});
export default connect(mapStateToProps, { register, createMessage })(
Tabset_user
);
Action.js:
This is an action creator where I use Axios to call post requests to register the user.
import * as types from "../../constants/actionTypes";
import axiosInstance from "./axios";
// LOGIN USER
export const login = (username, password) => (dispatch) => {
const body = {
username: username,
password: password,
};
axiosInstance
.post("api/token/obtain/", body)
.then((res) => {
console.log(res);
axiosInstance.defaults.headers["Authorization"] =
"JWT " + res.data.access;
dispatch({
type: types.LOGIN_SUCCESS,
payload: res.data,
});
})
.catch((err) => {
console.log(err);
// dispatch(returnErrors(err.response.data, err.response.status));
dispatch({
type: types.LOGIN_FAIL,
});
// alert("Invalid username and Password");
});
};
// REGISTER USER
export const register = ({
first_name,
last_name,
email,
username,
password,
phone,
gender,
}) => (dispatch) => {
// Request Body
// const body = {
// first_name: first_name,
// last_name: last_name,
// email: email,
// username: username,
// password: password,
// };
axiosInstance
.post("/api/user/create/", {
first_name,
last_name,
email,
username,
password,
phone,
gender,
})
.then((res) => {
console.log(res);
dispatch({
type: types.REGISTER_SUCCESS,
payload: res.data,
});
// history.push(`${process.env.PUBLIC_URL}/pages/create-page`);
})
.catch((err) => {
// dispatch(returnErrors(err.response.data, err.response.status));
dispatch({
type: types.REGISTER_FAIL,
});
});
};
//LOGOUT USER
export const logout = () => (dispatch) => {
try {
const response = axiosInstance.post("api/blacklist/", {
refresh_token: localStorage.getItem("refresh"),
});
if (
response
.then((data) => {
if (data.statusText === "Reset Content") {
localStorage.removeItem("access");
localStorage.removeItem("refresh");
axiosInstance.defaults.headers["Authorization"] = null;
dispatch({
type: types.LOGOUT_SUCCESS,
});
}
})
.catch((err) => console.log(err))
);
} catch (e) {
console.log(e);
}
};

Categories

Resources