I am creating simple form application that will input user data and insert them into MongoDB. I am using Axios for CRUD operations and all operations are working in backend (tested in Postman). When I created frontend part (ReactJS) I managed to display all users and delete them by ID. But POST method for creating new user is not working. I am getting 500 Internal server error.
Also I am using FormData and useState. But when calling handleSubmit() method, FormData is empty.
CreateUser.js
const CreateUser = () => {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [email, setEmail] = useState("");
const submitHandler = (e) => {
e.preventDefault();
const formData = new FormData();
formData.set("firstName", firstName);
formData.set("lastName", lastName);
formData.set("email", email);
dispatch(createNewUser(formData)); //calling POST function from UserActions.js
};
return (
<form onSubmit={submitHandler}>
<input
type="text"
placeholder="Enter your first name"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<input
type="text"
placeholder="Enter your last name"
value={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
<input
type="email"
placeholder="Enter your e-mail"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<button className="button" type="submit">
Create
</button>
</form>
);
};
export default CreateUser;
Also I am using Redux for state managment so I have my action setup too.
UserActions.js
export const createNewUser = (userData) => async (dispatch) => {
try {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const { data } = await axios.post("/api/v1/user/new", userData, config);
dispatch({
payload: data
});
} catch (error) {
console.log(error.response);
}
};
Console will display message that firstName lastName email are empty because their require value is set to true.
const userSchema = new mongoose.Schema({
firstName: {
type: String,
required: [true, "Please enter your first name"],
}.....
module.exports = mongoose.model("User", userSchema);
But when I am using console.log() to check their values on input, that works fine. Only passing those values to formData is not working. Or am I missing something else ?
Thanks
TLDR: FormData is empty when trying to submit inserted values to MongoDB while using Axios to POST data
Related
So I'm trying to validate if the user and password inserted are in the API database for now my code only asks for a username and a password and gives it a token given by the API even if the user does not exist.
My problem is how to call the API to validate if the user exists or not.
I'm trying to create an if cycle to communicate with the API but I'm not getting anywhere thoughts?
This is my code:
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import"./App.css";
const Login = () => {
const [username, setUsername] = useState("");
const [Password, setPassword] = useState("");
const [error] = useState(null);
const [loading] = useState(false);
const navigate = useNavigate();
const handleLogin = () => {
console.log("name------->", username);
console.log("pass------->", Password);
var axios = require("axios");
var data = JSON.stringify({
"password": Password,
"username": username,
});
var config = {
method: "post",
url: "https://api.secureme.pt/api/v1/auth/login",
headers: {
"Content-Type": "application/json",
},
data: data,
};
axios(config)
.then(function (response) {
console.log("token----->", response.data.token);
sessionStorage.setItem("token", response.data.token);
navigate("/home");
})
.catch(function (error) {
console.log(error);
});
};
return (
<div className="Login">
<div className="title">
Login
</div>
<br />
<br />
<div>
Username: <br />
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
<div>
Password: <br />
<input
type="password"
value={Password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<br />
{error && <div className="error">{error}</div>}
<input className="button"
type="button"
value={loading ? "Loading..." : "Login"}
disabled={loading}
onClick={handleLogin}
/>
</div>
);
};
export default Login;
I would 100% add that logic on the server end.
So your login endpoint: https://api.secureme.pt/api/v1/auth/login, would contain logic like;
Get username and password.
Check if username and password exist in database.
If so, return access token.
If not, handle accordingly by returning a failed auth error code.
That being said, if you're persistent to do it on the front end.
Without knowing what database you're using - it's difficult to share any examples.
But in your handleLogin() function, before your call the login endpoint with Axios, just before that - check if the username and password exist in the database.
To do this, obviously depending on the database - you would have to install/import relevant package(s) to make that request.
Another solution would be to have a separate endpoint on the server end that would check if the credentials exist and return a boolean.
It's difficult for me to figure out why the login functionality is not working in the simple authentication programme
I'm building with react and redux. I used django to create APIs, but I'm just starting out with react and redux. Whenever I try to login from the frontend
I get 404 Page Not Found error.
I have the following as part of the redux action (auth.jsx)
export const login = (email, password) => async dispatch => {
const config = {
headers: {
'Content-Type':'application/json'
}
};
const body = JSON.stringify({email, password});
try{
const res = await axios.post(`${process.env.REACT_APP_API_URL}/user/login`, body, config)
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
})
dispatch(load_user());
} catch (err){
dispatch({
type: LOGIN_FAIL,
})
}
console.log('You hit the wrong url')
}
Redux DevTools displays the catch in the try and catch block``type(pin):"LOGIN_FAIL"`
Login.jsx
const Login = ({ login }) => {
const [formData, setFormData] = useState({
email: '',
password: ''
});
const {email, password} = formData;
const onChange = e => setFormData ({ ...formData, [e.target.name]: e.target.value});
const onSubmit = e => {
e.preventDefault();
login(email, password);
}
return(
<div className='container'>
<Form onSubmit={e => onSubmit(e)}>
<Form.Group className="mb-3" controlId="formBasicEmail">
<Form.Control type="email" placeholder="example#email.com" onChange={e => onChange(e)} required />
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicPassword">
<Form.Control type="password" placeholder="Password" minLength='6' onChange={e => onChange(e)} required />
</Form.Group>
<Button variant="primary" type="submit">
Login
</Button>
<p>Don't have an account? <Link to='/account/register'>Register</Link></p>
<p>Forgotten password? <Link to = '/account/password-reset'>Reset your password</Link></p>
</Form>
</div>
)
// const mapStateToProps = state => ({
// })
}
export default connect(null, {login}) (Login)
When I click on the submit button I get 404 Page Not Found error. And I know that the axios function is not functioning properly
because the url for the login page is http://localhost:3000/user/login and the the API is process.env.REACT_APP_API_URL}/user/login as shown in the code
above. Also, REACT_APP_API_URL = 'http://localhost:8000' It's now obvious that the API I'm sending the post request to is http://localhost:8000/user/login.
If the registered user login details email is example#gmail.com and the password react-redux12345! when I try to login with those details I get the following url
output on the console http://localhost:3000/account/undefined/user/login (1)I dont't know why undefined is appearing in the middle of the
url instead of at the end. (2) I still don't know why undefined is present in the requested url. Please I want a solution to this.
I'm kinda new in programming and I'm learning how the web works, And Im working on this project using Supabase PostgreeSQL with Api, so what I want to do is write (send data to db), and I want to do it using only ReactJS but I don't know if this is possible, I have made something to work only with JS and the API keyes from SUPABASE, but I don't know if this is correct to do
import {useState} from 'react'
import {supabase} from '../db/supabase';
import Helmet from "helmet";
import {Link} from 'react-router-dom'
import styled from "styled-components";
const Container = styled.div``
const LeftContainer = styled.div``
const RightContainer = styled.div``
const Input = styled.input``
const BtnButBlack = styled.button``
const BtnButGreen = styled.button``
const Form = styled.form``
export default function Signup() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [name, setName] = useState('');
const [username, setUsername] = useState('');
const handleSubmit = (event) => {
new_account({email: email, password: password}, name, username)
event.preventDefault();
};
const handleEmail = (event) => {
event.preventDefault();
setEmail(event.target.value)
};
const handlePassword = (event) => {
event.preventDefault();
setPassword(event.target.value)
}
const handleName = (event) => {
event.preventDefault();
setName(event.target.value)
}
const handleUsername = (event) => {
event.preventDefault();
setUsername(event.target.value)
}
const new_account = async ({email, password}) => {
const {user, session, error} = await supabase.auth.signUp({
email: email,
password: password,
})
if (error) {
console.error(error)
return
}
console.log(user);
await supabase
.from('Users')
.insert([
{username: username, name: name, email: email, password: password}
])
};
return (
<Container>
<LeftContainer>
Signup
</LeftContainer>
<RightContainer>
<Form onSubmit={handleSubmit}>
<Input onChange={handleUsername} type="text" value={username} placeholder="Username" autoComplete="false" /><br></br>
<Input onChange={handleName} type="text" value={name} placeholder="Name" autoComplete="false" /><br></br>
<Input onChange={handleEmail} type="text" value={email} placeholder="Email" autoComplete="false" /><br></br>
<Input onChange={handlePassword} type="password" value={password} placeholder="Password" autoComplete="false" /><br />
<BtnButGreen>Sign Up</BtnButGreen>
</Form>
</RightContainer>
</Container>
)
}
and this is the supabase module that you can import and use it on the jsx file:
import {createClient} from '#supabase/supabase-js'
const supabaseUrl = process.env.REACT_APP_SUPABASE_URL
const supabaseAnonKey = process.env.REACT_APP_SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
The code you have seems great! With Supabase, the you are only exposing anon key and supabase URL, which are meant to be public.
You use row level security and Supabase Auth to prevent malicious attackers to hack your database. You can read more about row level security here:
https://supabase.io/docs/learn/auth-deep-dive/auth-row-level-security
If you have any questions, please don't hesitate to ask!
I do have a simple component with form. I want to use useSendEmail hook which returns the server response (success or failure). Where do I call this hook so it doesn't fire on the first render but only after I get my data from the user and save it in the state?
Expected behaviour: hook useSendEmail is called when the email object contains users input and returns status (if sent successfully or not).
I am aware I need to call hook at the top level in the component, but I do I wait for the data from input fields?
Actual behaviour: I am breaking the rule of hooks.
// importing everything I need here
const ContactPage = () => {
const initial = {
from: '',
message: '',
email: '',
};
const [formData, setFormData] = useState(initial);
const [email, setEmail] = useState(null);
const handleChange = ({ name, value }) => {
setFormData({ ...formData, [name]: value });
};
useEffect(() => {
if (email === null) return;
const response = useSendEmail(email);
}, [email]);
const handleSubmit = (e) => {
e.preventDefault();
setEmail(formData);
};
return (
<DefaultLayout title="Contact">
<StyledContainer>
<form className="contact_form" onSubmit={(e) => handleSubmit(e)}>
<input
name="from"
type="text"
value={formData.from}
onChange={(e) => handleChange(e.target)}
placeholder="Your full name"
/>
<textarea
name="message"
value={formData.message}
onChange={(e) => handleChange(e.target)}
placeholder="Your Message"
/>
<input
name="email"
type="email"
value={formData.email}
onChange={(e) => handleChange(e.target)}
placeholder="Your e-mail"
/>
<button type="submit">SUBMIT</button>
</form>
</StyledContainer>
</DefaultLayout>
);
};
export default ContactPage;
EDIT:
this is how my hook looks like after refactoring with your suggestions. I am now importing the hook and the method in the top level component and everything seems to work perfectly.
import { useState } from 'react';
import emailjs from 'emailjs-com';
import { userID, templateID, serviceID } from '../data/account';
const useSendEmail = (email) => {
const [response, setResponse] = useState(null);
const successMsg = 'Your message has been successfully sent';
const errorMsg = 'Your message has not been sent. Try again.';
const sendEmail = async () => emailjs
.send(serviceID, templateID, email, userID)
.then(
(res) => {
if (res.status === 200) {
setResponse(successMsg);
}
if (res.status !== 200) {
setResponse(errorMsg);
}
},
(err) => {
console.log(err);
},
);
return { response, sendEmail }
};
export default useSendEmail;
I'm making a form and below is the format. As you can see I was in two cases (for storing in multistage form) and upon clicking next on the second form we call {onSubmitform}. The problem which you can see is while entering data in form, I'm facing where to store it i.e, {onChange}.
Also ~ please let me know if this was {onSubmitform} will work to send data to the backend.
import React, { useEffect, useState } from 'react';
const Rider_Signup = ()=>{
const [step, setstep] = useState(1);
const [formdata, setFormData] = useState({zipcode:"", email:"",name:"",location:"", dob:"",phone:"",sex:"", password:"",aadhar:""}); // use to hold input from user
const onSubmitform = async e =>{
e.preventDefault();
try{
const email=formdata.email;
console.log(email);
const body={email};
const response = await fetch("http://localhost:5000/api/service/signup",{
method:"POST",headers:{"Content-Type":"application/json"},
body:JSON.stringify(body)
})
const datainjson = await response.json();
window.location =`/driver/login`;
}catch(err){
console.log('Error')
}
}
const renderForm = () =>{
switch(step){
case 1: return <div className="admin_form_div">
<h1 className="form_header">Hey ! </h1>
<center>
<form action="/initial" id="admin_form" name="admin_form">
<label for="Email" className="label">Enter the Email</label><br/>
<input type="email" name="name" className="Email" value={formdata.email} onChange={e =>{console.log(formdata.email)
setFormData(formdata.email=(e.target.value))}} placeholder="email#id.com" pattern="[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,}$" title="Please enter valid email" required />
<br/>
<br/>
<button onClick = {() => setstep(step+1)}>Submit</button>
</form>
</center>
</div>
case 2: return <div><h1>{formdata.email} </h1><button onClick = {() => setstep(step+1)}>Submit</button></div>
default: return <div> {onSubmitform}</div>
}
}
return (
renderForm()
)
};
export default Rider_Signup;
formdata is const and cant be reassigned,
formdata can only be changed with setFormData hook.
...formdata will save other fields when only the email is changing.
also, this is duplicated.
onChange={
e => {
console.log(formdata.email)
setFormData({ ...formdata, email: e.target.value })
}
}