I’m creating a tinder clone, I can create a user fine however I cant upload a picture. The error I get is ValidationError: User validation failed: pictures: Cast to embedded failed for value “‘picture'” at path “pictures”. I’m not sure what I’m doing wrong. The post request seems to fire as excepted with the payload however its when I login when I get the error. So I’m sure this has something to do with initial creation of the account.
create account front and back
import React, { useState } from "react"; import {useHistory } from "react-router-dom"; import axios from "axios"; const CreateAccount = () => { const api = "http://localhost:5000/user/create-account"; const history = useHistory(); const [firstName, setFirstName] = useState(""); const [lastName, setLastName] = useState(""); const [emailAddress, setEmailAddress] = useState(""); const [password, setPassword] = useState(""); const [gender, setGender] = useState("Male"); const [sexualPreference, setSexualPreference] = useState("Straight"); const [age, setAge] = useState(""); const [description, setDescription] = useState(""); const [picture, setPicture] = useState(""); const account = { firstName: firstName, lastName: lastName, emailAddress: emailAddress, password: password, gender: gender, sexualPreference: sexualPreference, age: age, description: description, pictures: picture }; console.log(account.gender); console.log(account.sexualPreference); console.log(account.pictures) const submit = () => { axios .post(api, account) .then((res) => { console.log(res.data); history.push({ pathname: "/", }); }) .catch((err) => console.log(err)); }; const handleSubmit = (event) => { event.preventDefault(); submit(); }; return ( <div> <div> <h1>Create account</h1> </div> <form onSubmit={handleSubmit} encType="multipart/form-data"> <p>First Name</p> <input id="firstName" name="firstName" type="firstName" onChange={(e) => setFirstName(e.target.value)} ></input> <p>Last Name</p> <input id="lastName" name="lastName" type="lastName" onChange={(e) => setLastName(e.target.value)} ></input> <p>Email Address</p> <input id="emailAddress" name="emailAddress" type="emailAddress" onChange={(e) => setEmailAddress(e.target.value)} ></input> <p>Password</p> <input id="password" name="password" type="password" onChange={(e) => setPassword(e.target.value)} ></input> <p>Gender</p> <select id="gender" name="gender" type="gender" onChange={(e) => setGender(e.target.value)} > <option value="Male">Male</option> <option value="Female">Female</option> </select> <p>Sexual Preference</p> <select id="sexualPreference" name="sexualPreference" type="sexualPreference" onChange={(e) => setSexualPreference(e.target.value)} > <option value="Straight" >Straight</option> <option value="Gay" >Gay</option> <option value="Lesbian" >Lesbian</option> <option value="Bisexual" >Bisexual</option> </select> <p>Age</p> <input id="age" name="age" type="age" onChange={(e) => setAge(e.target.value)} ></input> <p>Description</p> <input id="description" name="description" type="description" onChange={(e) => setDescription(e.target.value)} ></input> <input type="file" name="file" id="picture" onChange={(e) => setPicture(e.target.id)} ></input> <button type="submit">Submit</button> </form> </div> ); }; export default CreateAccount;
router.post( "/user/create-account", [ check("firstName") .exists({ checkNull: true, checkFalsy: true }) .withMessage('Please provide a value for "firstName"'), check("lastName") .exists({ checkNull: true, checkFalsy: true }) .withMessage('Please provide a value for "username"'), check("emailAddress") .exists({ checkNull: true, checkFalsy: true }) .withMessage('Please provide a value for "emailAddress"'), check("password") .exists({ checkNull: true, checkFalsy: true }) .withMessage('Please provide a value for "password"'), check("gender") .exists({ checkNull: true, checkFalsy: true }) .withMessage('Please provide a value for "gender"'), check("sexualPreference") .exists({ checkNull: true, checkFalsy: true }) .withMessage('Please provide a value for "sexualPreference"'), check("age") .exists({ checkNull: true, checkFalsy: true }) .withMessage('Please provide a value for "age"'), check("description") .exists({ checkNull: true, checkFalsy: true }) .withMessage('Please provide a value for "description"'), check("pictures") .exists({ checkNull: true, checkFalsy: true }) .withMessage('Please provide a value for "pictures"'), ], asyncHandler(async (req, res, next) => { // Attempt to get the validation result from the Request object. const errors = validationResult(req); // If there are validation errors... if (!errors.isEmpty()) { // Use the Array `map()` method to get a list of error messages. const errorMessages = errors.array().map((error) => error.msg); // Return the validation errors to the client. return res.status(400).json({ errors: errorMessages }); } //new user request body using mongo model from schema const postUser = new User({ firstName: req.body.firstName, lastName: req.body.lastName, emailAddress: req.body.emailAddress, password: req.body.password, gender: req.body.gender, sexualPreference: req.body.sexualPreference, age: req.body.age, description: req.body.description, pictures: req.body.pictures }); const userEmail = await User.findOne({ emailAddress: postUser.emailAddress, }); if (postUser.emailAddress === userEmail) { console.log("User with this email already exists"); return res.status(500).end(); } else if (postUser) { //if true salts the password with bcryptjs let salt = await bcryptjs.genSalt(10); const hashPass = await bcryptjs.hash(postUser.password, salt); console.log(hashPass); postUser.password = hashPass; postUser.save(); res.json({ postUser }); return res.status(201).end(); } else { res.status(400).send({ error: "Error: Account not created" }).end(); } }) );
mongoDb Schema
const mongoose = require('mongoose'); const userSchema = mongoose.Schema( { firstName:{ type: String, required: true }, lastName: { type: String, require: true }, emailAddress: { type: String, require: true }, password:{ type: String, required: true }, gender:{ type: String, required: true }, sexualPreference: { type: String, required: true }, age: { type: Number, required: true }, description: { type: String, required: true }, pictures: { type: [{ picURL: String, }], }, matches: { type: [{ Object }], }, }) module.exports = mongoose.model('User', userSchema);
login backend and frontend
router.post( "/login", asyncHandler(async (req, res, next) => { const userBody = req.body; const user = await User.findOne({ emailAddress: req.body.emailAddress }); if (userBody && user) { console.log(user); const authenticated = bcryptjs.compare(userBody.password, user.password); console.log(authenticated); if (authenticated) { console.log("match"); const accessToken = jwt.sign(user.toJSON(), process.env.ACCESS_TOKEN_SECRET, { expiresIn: 86400 }); res.cookie("token", accessToken, { httpOnly: false, maxAge: 86400 }); res.setHeader('Authorization', 'Bearer '+ accessToken); res.json({ user: user, accessToken: accessToken, }) .send() } else { res.status(403).send({ error: "Login failed: Please try again" }).end(); } } else { res.status(403).send({ error: "Login failed: Please try again" }).end(); } }) );
import React, { useState} from "react"; import { useHistory } from "react-router"; import axios from "axios"; import { Link } from "react-router-dom"; const api = 'http://localhost:5000'; export default function Login () { const history = useHistory(); const [ email, setEmail ] = useState(""); const [ pass, setPassword ] = useState(""); const submit = () => { axios.post(`${api}/login`, { emailAddress: email, password: pass }, {withCredentials: true, credentials: 'include'}) .then(res => { localStorage.setItem('jwt', res.data.accessToken); history.push({ pathname: `/user/account/${res.data.user._id}` }); }) .catch(err => console.log(err)); } const handleSubmit = (event) => { event.preventDefault(); submit() } return ( <div> <h1>Login</h1> <form onSubmit={handleSubmit}> <input id="emailAddress" name="emailAddress" type="text" placeholder="emailAddress" onChange={(e) => setEmail(e.target.value)} /> <input id="password" name="password" type="password" placeholder="Password" onChange={(e) => setPassword(e.target.value)} /> <button type="submit">Submit</button> <button >Cancel</button> </form> <p>Don't have a user account? <Link to="/user/create-account" >Click here</Link> to sign up! </p> </div> ); }
Advertisement
Answer
first of all you can’t upload image like this because you send regular http request if you want to send iamge you need to follow this steps
in the frontend you need to send the request with form data for more info read this blog from mdn what is formData mdn you can do something like that with axios append all of the req body to the formData and add it to the axios add multipart/form-data header
axios({ method: "post", url: "myurl", data: bodyFormData, headers: { "Content-Type": "multipart/form-data" }, }) .then(function (response) { // handle success }) .catch(function (response) { //handle error });
in the server you need to upload-files-or-images-to-server-using-nodejs