fetch send the data but doesn't go in then, React - javascript

I have problem with fetch. The data have been send, but doesn't do in then or catch, so I don't get if response is send ot not, only when I go in database. That is the code:
import React, { useState } from 'react'
// import styles from './index.module.css'
import Input from '../input'
import SignUpButton from '../sign-up-button'
const SignUpForm = () => {
const [username, setUsername] = useState('')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const handleSubmit = (e) => {
e.preventDefault()
let data = { username: username, email: email, password: password }
const headers = new Headers()
headers.append('Content-Type', 'application/json')
const options = {
method: 'POST',
headers: headers,
mode: 'cors',
cache: 'default',
body: JSON.stringify(data)
}
const request = new Request(`http://localhost:5000/user/sign-up`, options)
fetch(request)
.then(res => {
setUsername('')
setEmail('')
setPassword('')
})
.catch(e => {
console.log(e)
})
}
return (
<form onSubmit={handleSubmit}>
<Input
onChange={e => setUsername(e.target.value)}
label='Username:'
name='username'
placeholder='marolio'
value={username}
/>
<Input
onChange={e => setEmail(e.target.value)}
label='Email:'
name='email'
placeholder='marolio#yahoo.com'
value={email}
/>
<Input
onChange={e => setPassword(e.target.value)}
label='Password:'
name='password'
value={password}
/>
<SignUpButton
text='CREATE ACCOUNT'
btnStyle='submit'
/>
</form>
)
}
export default SignUpForm
Same structire worked for me in other project, so maybe something is changed but I don't know it. Every help will be useful. Thanks!

I made this change and it work, but I'm still curious why then and catch doesn't worked.
const response = fetch(request)
if(response){
setUsername('')
setEmail('')
setPassword('')
} else{
console.log('error')
}

Related

Sending form data from react client side to node.js server side

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>
);
}
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.
useEffect in this case absolutely unnecessary, so you have both and submit handler and useEffect that actually make you app rerender several extra times through setState, so Id build this something like that
import React from 'react';
import '../signIn/signIn.component.css'
import { Link } from "react-router-dom";
import { useState } from "react";
export default function SignIn() {
const [username, setUsername] = useState(null);
const [password, setPassword] = useState(null);
const submitFormSignIn = () => {
const testURL = "http://localhost:3100/login";
const myInit = {
method: "POST",
mode: 'no-cors',
body: JSON.stringify({ username, password }),
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>
//same jsx
</React.Fragment>
);
}

How to call API when submitting the form?

I have the API and Login form, separately. Now I want to send my login credentials to API.
i don't know about how to call API and return data. const handleSubmit = (e) => {} inside of this, how to call API?
//login page
const initialFormData = Object.freeze({
username: "",
password: ""
});
export function LoginForm(props) {
const { switchToSignup } = useContext(AccountContext);
const [formData, updateFormData] = React.useState(initialFormData);
const handleChange = (e) => {
updateFormData({
...formData,
//whitespace
[e.target.name]: e.target.value.trim()
});
};
const handleSubmit = (e) => {
e.preventDefault()
console.log(formData);
this.props.history.push('/auth')
};
return (
<BoxContainer className="mobiview">
<FormContainer>
<Input type="text" placeholder="User name" name="username" onChange={handleChange}/>
<Input type="password" placeholder="Password" name="password" onChange={handleChange}/>
</FormContainer>
<SubmitButton type="submit" onClick={handleSubmit}>Signin</SubmitButton>
</BoxContainer>
//API (Its in another folder)
export const authProvider = {
// authentication
login: ({ username, password }) => {
const request = new Request(url + "/auth", {
method: "POST",
body: JSON.stringify({ username, password }),
headers: new Headers({ "Content-Type": "application/json" }),
});
...
...
}
}
Import the auth file, invoke from handleSubmit
import authProvider from "./path-to-file";
const handleSubmit = (e) => {
e.preventDefault()
console.log(formData);
const { username, password } = formData;
authProvider.login({
username,
password
});
};

Can You Add Data to Database (supabase) without an Server using ReactJS

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!

React encrypt password

I have following component to pass data in my firestore database. Currently the password is not encrypted and and is visible to users of the database. Therefore I want to encrypt it. However, I get the error
TypeError: Cannot read property 'encrypt' of undefined.
That is my component for putting data in the database:
import React, {useState} from "react";
import fire from './fire.js';
import {userAuth} from './Main';
import '../style/inputPasswords.css';
import {encrypt} from './encryption';
const database = fire.firestore();
const InputPasswords = () => {
const [title, setTitle] = useState("");
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
let encryptedPassword = encrypt(password);
database.collection("password-"+userAuth).add({
title: title,
username: username,
password: encryptedPassword
})
.then(() => {
window.location.reload();
})
.catch((error) => {
console.error(error);
})
setTitle("");
setUsername("");
setPassword("");
}
return (
<form className="form" onSubmit={handleSubmit}>
<label>title</label>
<input className="input" id="title" placeholder="Title" value={title} autoComplete="off"
onChange={(e) => setTitle(e.target.value)}/>
<label>Username</label>
<input className="input" id="username" placeholder="Username" value={username} autoComplete="off"
onChange={(e) => setUsername(e.target.value)}/>
<label>Password</label>
<input className="input" id="password" placeholder="Password" type="password" value={password} autoComplete="off"
onChange={(e) => setPassword(e.target.value)}/>
<button type="submit">Add</button>
</form>
)
}
export default InputPasswords
This is the code for the encryption:
import crypto from "crypto";
const secret = "testtesttesttesttesttesttesttest";
const encrypt = (password) => {
return crypto.AES.encrypt(password, secret).toString();
};
const decrypt = (encryption) => {
let bytes = crypto.AES.decrypt(encryption, secret);
let originalText = bytes.toString(crypto.enc.Utf8);
return originalText;
};
export {encrypt, decrypt};
I am not sure how to fix that. Does anyone have an idea how to solve that problem?
Because without the encryption the code runs without any problems
I edited and moved the encryption function into the component and so the password gets encrypted
const handleSubmit = (e) => {
e.preventDefault();
const secret = "testtesttesttesttesttesttesttest";
const iv = Buffer.from(crypto.randomBytes(16));
const cipher = crypto.createCipheriv('aes-256-ctr', Buffer.from(secret), iv);
const encryptedPassword = Buffer.concat([cipher.update(password), cipher.final()]);
//let encryptedPassword = crypto.AES.encrypt("password", secret).toString();;
database.collection("password-"+userAuth).add({
title: title,
username: username,
password: encryptedPassword.toString('hex')
})
.then(() => {
window.location.reload();
})
.catch((error) => {
console.error(error);
})
setTitle("");
setUsername("");
setPassword("");
}

When should I call custom hook not breaking any rules of hooks?

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;

Categories

Resources