Including AWS function call removes app layout - reactjs

This is a picture of my react app before and after replacing a method handleSubmit from the following:
function handleSubmit(event) {
event.preventDefault();
}
with this:
async function handleSubmit(event) {
event.preventDefault();
try {
await Auth.signIn(email, password);
alert("Logged in");
} catch (e) {
alert(e.message);
}
}
As you can see the replacement of code removes the 'layout' of the app-page. I am new to AWS and React. Anyone has a clue what is wrong?
The entire Login.js container can be seen here:
import React, { useState } from "react";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import "./Login.css";
import { Auth } from "aws-amplify";
export default function Login() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
function validateForm() {
return email.length > 0 && password.length > 0;
}
async function handleSubmit(event) {
event.preventDefault();
try {
await Auth.signIn(email, password);
alert("Logged in");
} catch (e) {
alert(e.message);
}
}
return (
<div className="Login">
<Form onSubmit={handleSubmit}>
<Form.Group size="lg" controlId="email">
<Form.Label>Email</Form.Label>
<Form.Control
autoFocus
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</Form.Group>
<Form.Group size="lg" controlId="password">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</Form.Group>
<Button block size="lg" type="submit" disabled={!validateForm()}>
Login
</Button>
</Form>
</div>
);
}

Related

Why might I be getting a: TypeError: updatePassword is not a function

I have a simple react app with an update profile page, using firebase for auth, and when I try to change the password, I'm getting this error:TypeError: updatePassword is not a function.
Here is my UpdateProfile.js
import React, { useRef, useState } from "react";
import { Form, Button, Card, Alert } from "react-bootstrap";
import { getAuth } from "firebase/auth";
import { Link, useNavigate } from "react-router-dom";
export default function UpdateProfile() {
const emailRef = useRef();
const passwordRef = useRef();
const passwordConfirmRef = useRef();
const { currentUser, updateEmail, updatePassword } = getAuth();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
function handleSubmit(e) {
e.preventDefault();
if (passwordRef.current.value !== passwordConfirmRef.current.value) {
return setError("Passwords do not match");
}
const promises = [];
setLoading(true);
setError("");
if (emailRef.current.value !== currentUser.email) {
promises.push(updateEmail(emailRef.current.value));
}
if (passwordConfirmRef.current.value) {
promises.push(updatePassword(passwordRef.current.value));
}
Promise.all(promises)
.then(() => {
navigate("/");
})
.catch(() => {
setError("Failed to update account");
})
.finally(() => {
setLoading(false);
});
}
return (
<>
<Card>
<Card.Body>
<h2 className="text-center mb-4">Update Profile</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email">
<Form.Label>Email</Form.Label>
<Form.Control
type="email"
ref={emailRef}
required
defaultValue={currentUser.email}
/>
</Form.Group>
<Form.Group id="password" data-testid="pword">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
ref={passwordRef}
placeholder="Leave blank to keep the same"
/>
</Form.Group>
<Form.Group id="password-confirm">
<Form.Label>Password Confirmation</Form.Label>
<Form.Control
type="password"
ref={passwordConfirmRef}
placeholder="Leave blank to keep the same"
/>
</Form.Group>
<div className="w-100 mt-2">
<Button disabled={loading} className="w-100" type="submit">
Update
</Button>
</div>
</Form>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
<Link to="/">Cancel</Link>
</div>
</>
);
}
the Error points to line 30, which is here in stars:
if (emailRef.current.value !== currentUser.email) {
promises.push(updateEmail(emailRef.current.value));
}
if (passwordConfirmRef.current.value) {
**promises.push(updatePassword(passwordRef.current.value));**
}
Can anyone see what I have wrong? Thanks!
The updateEmail and updatePassword functions can be imported from Firebase Auth SDK and not the Auth instance. Try updating your import statements to:
import { updateEmail, updatePassword } from "firebase/auth"

xhr.js:210 POST http://localhost:3000/api/users/login 401 (Unauthorized)

Hello I am developing a login system and when I try to make a post request to localhost:5000/api/users login I get:
xhr.js:210 POST http://localhost:5000/api/users/login 401 (Unauthorized)
this is my code:
import React, { useState, useEffect} from "react";
import { Form, Button, Row, Col } from "react-bootstrap";
import { Link } from "react-router-dom";
import "./LoginScreen.css";
import axios from 'axios';
function LoginScreen() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const submitHandler = async (e) => {
e.preventDefault();
try {
const config = {
headers: {
"Content-type": "application/json",
},
};
setLoading(true);
const { data } = await axios.post(
"http://localhost:5000/api/users/login",
{
email,
password,
},
config);
console.log(data);
localStorage.setItem("userInfo", JSON.stringify(data));
setLoading(false);
} catch (error) {
setError(error.response.data.message);
console.log(error);
}
};
return (
<div className="login_outer">
<h1>Login Here</h1>
<div className="loginContainer">
<Form onSubmit={ submitHandler }>
<Form.Group controlId="formBasicEmail" >
<Form.Label>E-mail: </Form.Label>
<Form.Control size="lg" type="email" value={email} placeholder="Enter Email" className="input" onChange={(e) => setEmail(e.target.value)}/>
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Label>Password: </Form.Label>
<Form.Control size="lg" type="password" value={password} placeholder="Enter Password" className="input" onChange={(e) => setPassword(e.target.value)}/>
</Form.Group>
<Button className="login_button" variant="primary" type="submit">
Submit
</Button>
</Form>
<Row className="py-3">
<Col>
New User ? <Link to="/register">Register Here</Link>
</Col>
</Row>
</div>
</div>
);
}
export default LoginScreen;
Can anyone offer help with that ? I also have a proxy in the src folder. If I use postman for that request it does work.

Internal server error when attempting to register user in React/Redux app

I have a database on AtlasDB cloud service. In my React application, I want my code to save the data from the form below to be saved in the database, however I get internal server error (500) when I make a post request. What could be the problem here? The code of the React component is as follows:
import React, { useState, useEffect } from "react";
//state for form fields
import { Link } from "react-router-dom";
import { Form, Button, Row, Col } from "react-bootstrap";
import { useDispatch, useSelector } from "react-redux";
import Message from "../components/Message";
import Loader from "../components/Loader";
import FormContainer from "../components/FormContainer";
import { register } from "../actions/userActions";
const RegisterScreen = ({ location, history }) => {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [message, setMessage] = useState(null);
const dispatch = useDispatch();
const userRegister = useSelector((state) => state.userLogin);
const { loading, error, userInfo } = userRegister;
const redirect = location.search ? location.search.split("=")[1] : "/";
const goToLoginScreen = () => {
history.goBack();
}
useEffect(() => {
if (userInfo) {
history.push(redirect);
}
}, [history, userInfo, redirect]);
const submitHandler = (e) => {
e.preventDefault();
//dispatch register
if(password !== confirmPassword){
setMessage('Passwords do not match');
} else {
goToLoginScreen();
dispatch(register(name, email, password));
}
};
return (
<FormContainer>
<h1>Sign Up</h1>
{message && <Message variant="danger">{message}</Message>}
{error && <Message variant="danger">{error}</Message>}
{loading && <Loader />}
<Form onSubmit={submitHandler}>
<Form.Group controlId="name">
<Form.Label>Name </Form.Label>
<Form.Control
type="name"
placeholder="Enter name"
value={name}
onChange={(e) => setName(e.target.value)}
></Form.Control>
</Form.Group>
<Form.Group controlId="email">
<Form.Label>Email Address</Form.Label>
<Form.Control
type="email"
placeholder="Enter email"
value={email}
onChange={(e) => setEmail(e.target.value)}
></Form.Control>
</Form.Group>
<Form.Group controlId="password">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
placeholder="Enter password"
value={password}
onChange={(e) => setPassword(e.target.value)}
></Form.Control>
</Form.Group>
<Form.Group controlId="confirmPassword">
<Form.Label>Confirm Password</Form.Label>
<Form.Control
type="password"
placeholder="Confirm password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
></Form.Control>
</Form.Group>
<Button type="submit" variant="primary">
Register
</Button>
</Form>
<Row className="py-3">
<Col>
Have an account?{" "}
<Link to={redirect ? `/login?redirect=${redirect}` : "/login"}>
Login
</Link>
</Col>
</Row>
</FormContainer>
);
};
export default RegisterScreen;
It is very difficult to me to localize the error in code, whether it is a question of front-end or back-end. The user is not saved in the remote database.

Testing a component that uses context

I'm trying to write tests for the Login component of my app, and want to test that the user can enter email and password fields, then submit them. There are two complications: it has a to another component, and it uses context to import a function called loginUser. The first problem I solve by making a custom renderWithRouter function, but I can't solve the second problem because the component isn't able to consume the loginUser function outside of context. I get this error: Error: Uncaught [TypeError: Cannot read property 'then' of undefined] because loginUser is undefined. Any idea how I can solve this? Here is Login.tsx:
import React, { useState } from 'react';
import { useAuth } from 'context/authContext'
import { useHistory, Link } from 'react-router-dom'
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button'
export const Login = (props: any) => {
const { setUser, loginUser } = useAuth()
const [email, setEmail] = useState<string>();
const [password, setPassword] = useState<string>();
const [errors, setErrors] = useState<boolean>()
const history = useHistory()
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
loginUser({
email,
password
}).then((result: any) => {
console.log(result)
if (result.message === 'login error') {
setErrors(true)
} else {
history.push('/dashboard/home')
}
})
}
return(
<div className="login-wrapper">
<h1>Please Log In</h1>
<div className='form-wrapper'>
<Form onSubmit={handleSubmit}>
<Form.Group controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control
isInvalid={errors ? true : false}
type="email"
placeholder="Enter email"
onChange={e => setEmail(e.target.value)}/>
<Form.Control.Feedback type="invalid">
{errors ? 'either you don\'t have an account or the email and password do not match' : null}
</Form.Control.Feedback>
<Form.Text className="text-muted">
umm..
</Form.Text>
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
placeholder="Password"
onChange={e => setPassword(e.target.value)}
/>
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
<div>
<Link to='/register'>new user? click here to register</Link>
</div>
</Form>
</div>
</div>
)
}
And Login.test.tsx:
test("allows user to input their email", () => {
const onSubmit = jest.fn();
renderWithRouter(<Login />)
const input = screen.getByLabelText("Email address")
const pwd = screen.getByLabelText("Password")
const button = screen.getByText("Submit")
fireEvent.change(input, { target: { value: "t#t.com"}})
fireEvent.change(pwd, { target: { value: "123456"}})
fireEvent.click(button)
expect(onSubmit).toBeCalled()
})
})
Haven't run it but refactor to something like this and then test the LoginForm component.
import React, { useState } from 'react';
import { useAuth } from 'context/authContext'
import { useHistory, Link } from 'react-router-dom'
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button'
interface LoginFormProps {
onSubmit: (email: string, password: string) => void;
errors: boolean;
}
export const LoginForm: React.FC<LoginFormProps> = ({onSubmit, errors}) => {
const [email, setEmail] = useState<string>();
const [password, setPassword] = useState<string>();
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
onSubmit(email, password)
}
return(
<div className="login-wrapper">
<h1>Please Log In</h1>
<div className='form-wrapper'>
<Form onSubmit={handleSubmit}>
<Form.Group controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control
isInvalid={errors ? true : false}
type="email"
placeholder="Enter email"
onChange={e => setEmail(e.target.value)}/>
<Form.Control.Feedback type="invalid">
{errors ? 'either you don\'t have an account or the email and password do not match' : null}
</Form.Control.Feedback>
<Form.Text className="text-muted">
umm..
</Form.Text>
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
placeholder="Password"
onChange={e => setPassword(e.target.value)}
/>
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
<div>
<Link to='/register'>new user? click here to register</Link>
</div>
</Form>
</div>
</div>
)
}
export const Login = (props: any) => {
const { setUser, loginUser } = useAuth()
const [errors, setErrors] = useState<boolean>(false)
const history = useHistory()
const handleSubmit = (email, password) => {
loginUser({
email,
password
}).then((result: any) => {
console.log(result)
if (result.message === 'login error') {
setErrors(true)
} else {
history.push('/dashboard/home')
}
})
}
return(
<LoginForm onSubmit={handleSubmit} errors={errors} />
)
}

Firebase Authentication not working with React

I have a simple app using React and Firebase (Cloud Firestore & Authentication).
I have used Firebase Authentication Sign in/ sign up with email and password but the promises have no response, although it worked well last night, and firebase.auth().onStateAuthChanged is not working neither but firebase.auth().sendPasswordResetEmail() works well. I do not know what is wrong?
You can check my code at: https://lfddm.csb.app/ (I've used codesandbox)
The firebase cloud firestore rules:
match /users/{userId} {
allow create: if request.auth.uid != null
allow read, write: if request.auth.uid == userId
}
The SignIn component:
import React, { useState } from "react";
import { Link } from "react-router-dom";
import {
Button,
Modal,
ModalHeader,
ModalBody,
Form,
FormGroup,
Label,
Input
} from "reactstrap";
import firebase from "../config/firebase";
export default function SignInModal(props) {
const [modal, setModal] = useState(false);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const resetModal = () => {
setModal(false);
setEmail("");
setPassword("");
};
const signIn = (e, p) => {
// console.log(e, p);
firebase
.auth()
.signInWithEmailAndPassword(e, p)
.then(() => alert("Sign in successfully!"))
.then(() => resetModal())
.catch(err => alert(err.message));
};
const styles = {
signModal: {
display: "inline",
margin: "0 3px"
}
};
return (
<div className="SignModal" style={styles.signModal}>
<Button color="primary" onClick={() => setModal(!modal)}>
Sign In
</Button>
<Modal isOpen={modal} toggle={() => resetModal()}>
<ModalHeader toggle={() => resetModal()}>Sign In</ModalHeader>
<ModalBody>
<Form
onSubmit={e => {
e.preventDefault();
signIn(email, password);
}}
>
<FormGroup>
<Label for="email">Email</Label>
<Input
type="email"
id="email"
value={email}
onChange={e => setEmail(e.target.value)}
required
/>
</FormGroup>
<FormGroup>
<Label for="password">Password</Label>
<Input
type="password"
id="password"
value={password}
onChange={e => setPassword(e.target.value)}
required
/>
</FormGroup>
<Button
type="submit"
color="primary"
style={{ marginRight: "5px" }}
>
Sign In
</Button>
<Link to="/forget-password">Forget password</Link>
</Form>
</ModalBody>
</Modal>
</div>
);
}
signIn function does not return anything, it means that the firebase.auth() promise is pending.

Resources