I am sending an axios put request to update Profile details. I have also got a non editable email field, in this case how can I send email id along with Axios.put(.. request.
While setting a breakpoint in server side, I could see the edited field values are available in req.body
I have grab the email as below, but not sure how to send along with updateProfile:
const userEmail = document.getElementsByName('email').value;
server.js
app.put('/service/profile', async (req, res, next) => {
try {
const userEmail = req.body.userEmail;
var selector = {
where: { email: userEmail }
};
const updatePlayer = await UserModel.update(req.body, selector);
console.log("Server side update method log:" + updatePlayer);
res.status(200).json({ success: true });
} catch (err) {
//res.status(500).json({ message: e.message })
return next(err);
}
});
Profile.js
const [playerProfile, setPlayerProfile] = useState([]);
const [updateProfile, setUpdateProfile] = useState({ _id: '', photo: '', name: '', email: '', phonenumber: '', position: '', password: '' })
const handleChange = (e, id) => {
e.persist();
let itemIndex;
const targetPlayer = playerProfile.find((player, index) => {
console.log({ player, id, index });
itemIndex = index;
return player.id === id;
});
console.log({ targetPlayer, id, e });
const editedTarget = {
...targetPlayer,
[e.target.name]: e.target.value
};
const tempPlayers = Array.from(playerProfile);
tempPlayers[itemIndex] = editedTarget;
setPlayerProfile(tempPlayers);
setUpdateProfile({ ...updateProfile, [e.target.name]: e.target.value });
};
const onSubmit = () => {
setDisabled(disabled);
const fetchData = async () => {
try {
const userEmail = document.getElementsByName('email').value;
const res = await Axios.put('http://localhost:8000/service/profile', updateProfile, userEmail);
console.log("Front End update message:" + res.data.success);
if (res.data.success) {
setIsSent(true);
history.push('/')
}
else {
console.log(res.data.message);
setHelperText(res.data.message);
}
} catch (e) {
setHelperText(e.response.data.message);
}
}
fetchData();
}
return (
<div className="register_wrapper">
<div className="register_player_column_layout_one">
<div className="register_player_Twocolumn_layout_two">
<form onSubmit={handleSubmit(onSubmit)} className="myForm">
{
playerProfile.map(({ id, photo, name, email, phonenumber, position, privilege, password }) => (
<div key={id}>
<div className="fillContentDiv formElement">
<label>
<input className="inputRequest formContentElement" name="name" type="text" value={name}
onChange={e => handleChange(e, id)}
maxLength={30}
ref={register({
required: "Full name is required",
pattern: {
value: /^[a-zA-Z\s]{3,30}$/,
message: "Full name should have minimum of 3 letters"
}
})}
/>
<span className="registerErrorTextFormat">{errors.name && errors.name.message}</span>
</label>
<label>
<input className="inputRequest formContentElement" name="email" type="text" value={email}
onChange={e => handleChange(e, id)}
disabled={disabled}
/>
</label>
<label>
<input className="inputRequest formContentElement" name="phonenumber" type="text" value={phonenumber}
onChange={e => handleChange(e, id)}
maxLength={11}
ref={register({
required: "Phone number is required",
pattern: {
value: /^[0-9\b]+$/,
message: "Invalid phone number"
}
})}
/>
<span className="registerErrorTextFormat">{errors.phonenumber && errors.phonenumber.message}</span>
</label>
<label>
<input className="inputRequest formContentElement" name="position" type="text" value={position} onChange={e => handleChange(e, id)}/>
</label>
<label>
<div className="select" >
<select name="privilege" id="select" value={privilege} onChange={e => handleChange(e, id)}>
<option value="player">PLAYER</option>
{/*<option value="admin">ADMIN</option>*/}
</select>
</div>
</label>
<label>
<input className="inputRequest formContentElement" name="password" type="password" value={password}
onChange={e => handleChange(e, id)}
minLength={4}
maxLength={30}
ref={register({
required: "Password is required",
pattern: {
value: /^(?=.*?\d)(?=.*?[a-zA-Z])[a-zA-Z\d]+$/,
message: "Password begin with a letter and includes number !"
}
})}
/>
<span className="registerErrorTextFormat">{errors.password && errors.password.message}</span>
</label>
</div>
<label>
<span className="profileValidationText">{helperText}</span>
</label>
<div className="submitButtonDiv formElement">
<button type="submit" className="submitButton">Save</button>
</div>
</div>
))
}
</form>
</div>
</div>
</div>
);
after getting app from express()
write
app.use(express.urlencoded({extended:false}))
Related
How can I solve the Axios Error in my code using the try/catch method . Am building a chat application with react js and stream API, when I try to signup using my signup form I get the Axios error which I don't know how I can debug it. You can help me out by editing my attached code so that i can continue with my project. Thanks in advance.
// below is my code//
import React, { useState } from 'react';
import Cookies from 'universal-cookie';
import axios from 'axios';
import signinImage from '../assets/signup.jpg';
const cookies = new Cookies();
const initialState = {
fullName: '',
username: '',
password: '',
confirmPassword: '',
phoneNumber: '',
avatarURL: '',
}
const Auth = () => {
const [form, setForm] = useState(initialState);
const [isSignup, setIsSignup] = useState(true);
const handleChange = (e) => {
setForm({ ...form, [e.target.name]: e.target.value });
}
const handleSubmit = async (e) => {
e.preventDefault();
const { username, password, phoneNumber, avatarURL } = form;
const URL = 'https://localhost:5000/auth';
// const URL = 'https://medical-pager.herokuapp.com/auth';
const { data: { token, userId, hashedPassword, fullName } } = await axios.post(`${URL}/${isSignup ? 'signup' : 'login'}`, {
username, password, fullName: form.fullName, phoneNumber, avatarURL,
});
cookies.set('token', token);
cookies.set('username', username);
cookies.set('fullName', fullName);
cookies.set('userId', userId);
if(isSignup) {
cookies.set('phoneNumber', phoneNumber);
cookies.set('avatarURL', avatarURL);
cookies.set('hashedPassword', hashedPassword);
}
window.location.reload();
}
const switchMode = () => {
setIsSignup((prevIsSignup) => !prevIsSignup);
}
return (
<div className="auth__form-container">
<div className="auth__form-container_fields">
<div className="auth__form-container_fields-content">
<p>{isSignup ? 'Sign Up' : 'Sign In'}</p>
<form onSubmit={handleSubmit}>
{isSignup && (
<div className="auth__form-container_fields-content_input">
<label htmlFor="fullName">Full Name</label>
<input
name="fullName"
type="text"
placeholder="Full Name"
onChange={handleChange}
required
/>
</div>
)}
<div className="auth__form-container_fields-content_input">
<label htmlFor="username">Username</label>
<input
name="username"
type="text"
placeholder="Username"
onChange={handleChange}
required
/>
</div>
{isSignup && (
<div className="auth__form-container_fields-content_input">
<label htmlFor="phoneNumber">Phone Number</label>
<input
name="phoneNumber"
type="text"
placeholder="Phone Number"
onChange={handleChange}
required
/>
</div>
)}
{isSignup && (
<div className="auth__form-container_fields-content_input">
<label htmlFor="avatarURL">Avatar URL</label>
<input
name="avatarURL"
type="text"
placeholder="Avatar URL"
onChange={handleChange}
required
/>
</div>
)}
<div className="auth__form-container_fields-content_input">
<label htmlFor="password">Password</label>
<input
name="password"
type="password"
placeholder="Password"
onChange={handleChange}
required
/>
</div>
{isSignup && (
<div className="auth__form-container_fields-content_input">
<label htmlFor="confirmPassword">Confirm Password</label>
<input
name="confirmPassword"
type="password"
placeholder="Confirm Password"
onChange={handleChange}
required
/>
</div>
)}
<div className="auth__form-container_fields-content_button">
<button>{isSignup ? "Sign Up" : "Sign In"}</button>
</div>
</form>
<div className="auth__form-container_fields-account">
<p>
{isSignup
? "Already have an account?"
: "Don't have an account?"
}
<span onClick={switchMode}>
{isSignup ? 'Sign In' : 'Sign Up'}
</span>
</p>
</div>
</div>
</div>
<div className="auth__form-container_image">
<img src={signinImage} alt="sign in" />
</div>
</div>
)
}
export default Auth
const handleSubmit = async (e) => {
e.preventDefault();
try {
const { username, password, phoneNumber, avatarURL } = form;
const URL = 'https://localhost:5000/auth';
// const URL = 'https://medical-pager.herokuapp.com/auth';
const { data: { token, userId, hashedPassword, fullName } } = await axios.post(`${URL}/${isSignup ? 'signup' : 'login'}`, {
username, password, fullName: form.fullName, phoneNumber, avatarURL,
});
cookies.set('token', token);
cookies.set('username', username);
cookies.set('fullName', fullName);
cookies.set('userId', userId);
if(isSignup) {
cookies.set('phoneNumber', phoneNumber);
cookies.set('avatarURL', avatarURL);
cookies.set('hashedPassword', hashedPassword);
}
window.location.reload();
} catch(error) {
console.log(error.response);
}
}
So I have a form, and I need users to fill this form and when they send a message, it should come to my gmail. I use EmailJS service for this.
So my form looks like this:
So as you see, users can send me messages, and my code looks like this:
Usestate for sending data:
const [toSend, setToSend] = useState({
from_name: '',
to_name: '',
message: '',
reply_to: '',
subject: ''
});
onSubmit function:
const onSubmit = (e) => {
e.preventDefault();
send(
'service_id',
'template_id',
toSend,
'user_id'
)
.then((response) => {
console.log('SUCCESS!', response.status, response.text);
})
.catch((err) => {
console.log('FAILED...', err);
});
reset();
};
handleChange function:
const handleChange = (e) => {
setToSend({ ...toSend, [e.target.name]: e.target.value });
};
useform hook:
const {register, handleSubmit, formState: { errors }, reset, trigger} = useForm();
Whole form:
<form onSubmit={handleSubmit(onSubmit)}>
<input type="text"
placeholder="Name"
name="from_name"
value={toSend.from_name}
onChange={handleChange}
id="name" {...register('name', { required: "Name is required" })}
onKeyUp={() => {
trigger("name");
}}/>
{errors.name && (<span className="danger_text">{errors.name.message}</span>)}
<input type="text"
placeholder="Email"
name="reply_to"
value={toSend.reply_to}
onChange={handleChange}
id="email" {...register("email", { required: "Email is Required" ,
pattern: {
value: /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: "Invalid email address",
}})}
onKeyUp={() => {
trigger("email");
}}
/>
{errors.email && (
<small className="danger_text">{errors.email.message}</small>
)}
<input type="text"
placeholder=
"Subject"
id="subj"
name="subject"
value={toSend.subject}
onChange={handleChange}/>
<input type="text"
placeholder="Message"
id="msg"
name="message"
value={toSend.message}
onChange={handleChange}
{...register('msg', { required: true })}/>
{errors.msg && (<small className="danger_text">Enter your message</small>)}
<input type="submit" className="btn_red" value="Send a message"></input>
</form>
So my problem is that I can't fill anything in inputs. When I try to type something it just doesn't type in, I'm guessing it has something to do with "value=.." in all inputs, but I'm not sure what's exactly the problem here.
You don't need to define onChnage, value, onKeyUp on your inputs, when you call register on input, it returns onChange,onBlur,ref, then react-hook-forms will control the values by ref. so below example should solve your problem:
import { useForm } from 'react-hook-form';
...
function MyComp() {
const {
register,
handleSubmit,
formState: { errors },
reset,
} = useForm();
const onSubmit = (toSend) => {
send(
'service_id',
'template_id',
toSend,
'user_id'
)
.then((response) => {
console.log('SUCCESS!', response.status, response.text);
})
.catch((err) => {
console.log('FAILED...', err);
});
reset();
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
type="text"
placeholder="Name"
name="from_name"
id="name"
{...register('from_name', { required: 'Name is required' })}
/>
{errors.from_name && (
<span className="danger_text">{errors.from_name.message}</span>
)}
<input
type="text"
placeholder="Email"
name="reply_to"
id="email"
{...register('reply_to', {
required: 'Email is Required',
pattern: {
value: /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address',
},
})}
/>
{errors.reply_to && (
<small className="danger_text">{errors.reply_to.message}</small>
)}
<input
type="text"
placeholder="Subject"
id="subj"
name="subject"
{...register('subject')}
/>
<input
type="text"
placeholder="Message"
id="msg"
name="message"
{...register('message', { required: true })}
/>
{errors.message && <small className="danger_text">Enter your message</small>}
<input type="submit" className="btn_red" value="Send a message"></input>
</form>
);
}
BTW, consider that register works with input's name, not id.
I have three radio buttons and I need to put the value of the selected one in inputs.reply, just like I did with inputs.name, inputs.email, inputs.phone and inputs.message. How can I do this? I know it's probably a very easy thing to do, but I've been trying for hours and it doesn't work.
import Head from 'next/head'
import React, { useState } from 'react'
export default () => {
const [status, setStatus] = useState({
submitted: false,
submitting: false,
info: { error: false, msg: null }
})
const [inputs, setInputs] = useState({
reply: '',
name: '',
phone: '',
email: '',
message: ''
})
function SubmitButton(){
if (inputs.name && inputs.email && inputs.message) {
return <button type="submit" className="btn-submit" disabled={status.submitting}> {!status.submitting ? !status.submitted ? 'Submit' : 'Submitted' : 'Submitting...'} </button>
} else {
return <button type="submit" className="btn-submit" disabled>Submit</button>
};
};
const handleResponse = (status, msg) => {
if (status === 200) {
setStatus({
submitted: true,
submitting: false,
info: { error: false, msg: msg }
})
setInputs({
reply: '',
name: '',
phone: '',
email: '',
message: ''
})
} else {
setStatus({
info: { error: true, msg: msg }
})
}
}
const handleOnChange = e => {
e.persist()
setInputs(prev => ({
...prev,
[e.target.id]: e.target.value
}))
setStatus({
submitted: false,
submitting: false,
info: { error: false, msg: null }
})
}
const handleOnSubmit = async e => {
e.preventDefault()
setStatus(prevStatus => ({ ...prevStatus, submitting: true }))
const res = await fetch('/api/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(inputs)
})
const text = await res.text()
handleResponse(res.status, text)
}
return (
<div className="contact">
<main>
<div className="content">
<div>
<h2>Get in touch!</h2>
<h3>How can we help you?</h3>
</div>
<form onSubmit={handleOnSubmit}>
<h4>How would you like us to get back to you?</h4>
<div className="form-group form-group-radio">
<div>
<input type="radio" onChange={handleOnChange} value="Phone" name="email-reply" id="reply-phone" />
<label className="radio-label" htmlFor="reply-phone">Phone</label>
</div>
<div>
<input type="radio" onChange={handleOnChange} value="E-mail" name="email-reply" id="reply-email" />
<label className="radio-label" htmlFor="reply-email">E-mail</label>
</div>
<div>
<input type="radio" onChange={handleOnChange} value="No reply needed" name="email-reply" id="no-reply" />
<label className="radio-label" htmlFor="no-reply">No reply needed</label>
</div>
</div>
<div className="form-group">
<input
id="name"
type="text"
name="name"
onChange={handleOnChange}
required
value={inputs.name}
className={inputs.name ? "form-control active" : "form-control"}
/>
<label className="form-label" htmlFor="name">Name</label>
</div>
<div className="form-group">
<input
id="email"
type="text"
name="email"
onChange={handleOnChange}
required
value={inputs.email}
className={inputs.email ? "form-control active" : "form-control"}
/>
<label className="form-label" htmlFor="email">Email</label>
</div>
<div className="form-group">
<input
id="phone"
type="tel"
name="phone"
onChange={handleOnChange}
required
value={inputs.phone}
className={inputs.phone ? "form-control active" : "form-control"}
/>
<label className="form-label" htmlFor="phone">Phone</label>
</div>
<div className="form-group">
<textarea
id="message"
onChange={handleOnChange}
required
value={inputs.message}
className={inputs.message ? "form-control active" : "form-control"}
/>
<label className="form-label" htmlFor="message">Message</label>
</div>
<SubmitButton />
{status.info.error && (
<div className="message-feedback error">
<p>Error: {status.info.msg}</p>
</div>
)}
{!status.info.error && status.info.msg && (
<div className="message-feedback success">
<p>Thanks for messaging us!</p>
<p>We'll get back to you soon.</p>
</div>
)}
</form>
</div>
</main>
</div>
)
}
Thank you.
Remove the id attribute from all of the <input type="radio" /> and instead add a name="reply" to all of them.
Now update handleOnChange, specifically this part
setInputs(prev => ({
...prev,
[e.target.id || e.target.name]: e.target.value
}))
You can update the handleOnChange method to check for the type of the target event and if its a radio button, you can update the radio state, otherwise use the dynamic key to update the state.
const handleOnChange = (e) => {
e.persist();
const key = e.target.type === "radio" ? "reply" : e.target.id;
setInputs((prev) => ({
...prev,
[key]: e.target.value
}));
setStatus({
submitted: false,
submitting: false,
info: { error: false, msg: null }
});
};
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;
I am not being able to change input fields.Any suggestion?
const MiddlePanel = ({ user }) => {
const history = useHistory();
const [data, setData] = useState({
firstname: '',
lastname: '',
email: '',
phoneNo: '',
});
const { firstname, lastname, email, phoneNo } = data;
useEffect(() => {
const fetchUser = async () => {
const res = await axios.get(`http://localhost:5000/users/${user._id}`);
setData({
firstname: res.data.firstname,
lastname: res.data.lastname,
email: res.data.email,
password: res.data.password,
});
};
fetchUser();
}, [user._id]);
const handleChange = (e) => {
setData({ ...data, [e.target.name]: e.target.value });
};
const handleSubmit = async (e) => {
e.preventDefault();
const newUser = { firstname, lastname, email, phoneNo };
try {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify(newUser);
await axios.patch(
`http://localhost:5000/users/${user._id}`,
body,
config
);
history.push("/");
} catch (err) {}
};
return (
<div>
<Form onSubmit={handleSubmit}>
<Input
type="text"
name="firstname"
onChange={handleChange}
value={user.firstname}
/>
<Input
type="text"
name="lastname"
onChange={handleChange}
value={user.lastname}
/>
<Input
type="email"
name="email"
onChange={handleChange}
value={user.email}
/>
<Input
type="tel"
name="phoneNo"
onChange={handleChange}
value={user.phoneNo}
/>
<PrimaryButton className="btn btn-primary" style={{ width: "100%" }}>
Update
</PrimaryButton>
</Form>
</div>
);
};
I think you should use data.firstname instead of user for the value property
<div>
<Form onSubmit={handleSubmit}>
<Input
type="text"
name="firstname"
onChange={handleChange}
value={data.firstname}
/>
<Input
type="text"
name="lastname"
onChange={handleChange}
value={data.lastname}
/>
<Input
type="email"
name="email"
onChange={handleChange}
value={data.email}
/>
<Input
type="tel"
name="phoneNo"
onChange={handleChange}
value={data.phoneNo}
/>
<PrimaryButton className="btn btn-primary" style={{ width: "100%" }}>
Update
</PrimaryButton>
</Form>
</div>