I have a login form at the client side (react) that I try to submit and pass the credentials to the login function at the server side (node.js)
when I use postman to send raw json object with the user name and password it works fine, but when I sent it through the client side the req.body contains only this: [[Prototype]]: Object
what am I doing wrong here?
here is the code of the component that contains the form:
import React from 'react';
import '../signIn/signIn.component.css'
import { Link } from "react-router-dom";
import { useState, useEffect } from "react";
export default function SignIn() {
const [UserName, setUsername] = useState(null);
const [PassWord, setPassWord] = useState(null);
const [FormData, setFormData] = useState({});
useEffect(() => {
setFormData({ UserName: UserName, PassWord: PassWord });
}, []);
const submitFormSignIn = () => {
const testURL = "http://localhost:3100/login";
const myInit = {
method: "POST",
mode: 'no-cors',
body: JSON.stringify(FormData),
headers: {
'Content-Type': 'application/json'
},
};
const myRequest = new Request(testURL, myInit);
fetch(myRequest).then(function (response) {
return response;
}).then(function (response) {
console.log(response);
}).catch(function (e) {
console.log(e);
});
}
return (
<React.Fragment>
<form onSubmit={(e) => { submitFormSignIn(); e.preventDefault(); }}>
<div className="signIn-form-container">
<h1 className="welcome-header">Welcome</h1>
<div className="userName-form-container">
<input className="input-user-name" type="text" name="userName" placeholder='User name'
//should start with an alphabet so. All other characters can be alphabets, numbers or an underscore so.
required
pattern="^[A-Za-z][A-Za-z0-9_]{7,29}$"
minLength={"6"}
maxLength={"20"}
onChange={(e) => setUsername(e.target.value)}
></input>
</div>
<div className="password-form-container">
<input className="input-password" type="password" name="passWord" required
//Minimum eight characters, at least one uppercase letter, one lowercase letter and one number:
pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$"
autoComplete="on"
minLength={"9"}
maxLength={"20"}
placeholder='Password'
onChange={(e) => setPassWord(e.target.value)}
></input>
</div>
<div className="forgot-remember-container">
<Link className="userName-forgot-link" to="/userNameRecovery">Forgot user name?</Link>
<Link className="password-forgot-link" to="/passwordRecovery">Forgot password?</Link>
</div>
<div className="form-submit-btn-container">
<button className="form-submit-btn">Sign in</button>
</div>
<div className="sign-up-container">
<a>Don't have an account?</a>
<Link className="signUp-link" to="/register">Sign up</Link>
</div>
<hr></hr>
</div>
</form>
</React.Fragment>
);
}
CodePudding user response:
Your useEffect is fired only once - after initial render, because it's dependency array is empty. It means, you don't set for formData state with proper data.
I see two solutions:
Either fill the dependency array with UserName
and PassWord
states:
useEffect(() => {
setFormData({ UserName: UserName, PassWord: PassWord });
}, [UserName, PassWord]);
Or - and I would recommend this - easily create your body Object directly from UserName and PassWord states to :
body: JSON.stringify({UserName, PassWord}),
Small underline notice: states are variables, so their name should be camelCase, with lowercase at the beginning. Variables with UpperCase are intended to be React Components.