I am creating a simple login page using react js and Django api. I am able to login but unable to go to my dashboard as it is throwing error like "Unhandled Rejection (TypeError): Cannot read property 'status' of undefined"
I am using Visual Studio Code
The full code is as below:
Login.js
import React, { useState } from 'react';
import axios from 'axios';
import { setUserSession } from './Utils/Common';
function Login(props) {
const [loading, setLoading] = useState(false);
const username = useFormInput('');
const password = useFormInput('');
const [error, setError] = useState(null);
// handle button click of login form
const handleLogin = () => {
setError(null);
setLoading(true);
axios.post('http://localhost:8000/account/user/signin', { mobile_number: username.value,
password: password.value }).then(response => {
setLoading(false);
setUserSession(response.data.token, response.data.user);
props.history.push('/dashboard');
}).catch(error => {
setLoading(false);
if (error.response.status === undefined) setError(error.response.data.message);
else setError("Something went wrong. Please try again later.");
});
}
return (
<div>
Login<br /><br />
<div>
Username<br />
<input type="text" {...username} autoComplete="new-password" />
</div>
<div style={{ marginTop: 10 }}>
Password<br />
<input type="password" {...password} autoComplete="new-password" />
</div>
{error && <><small style={{ color: 'red' }}>{error}</small><br /></>}<br />
<input type="button" value={loading ? 'Loading...' : 'Login'} onClick={handleLogin}
disabled={loading} /><br />
</div>
);
}
const useFormInput = initialValue => {
const [value, setValue] = useState(initialValue);
const handleChange = e => {
setValue(e.target.value);
}
return {
value,
onChange: handleChange
}
}
export default Login;
Dashboard.js
import React from 'react';
import { getUser, removeUserSession } from './Utils/Common';
function Dashboard(props) {
const user = getUser();
//handle click event of logout button
const handleLogout = () => {
removeUserSession();
props.history.push('/login');
}
return (
<div>
Welcome {user.name}!<br /><br />
<input type="button" onClick={handleLogout} value="Logout" />
</div>
);
}
export default Dashboard;
Related
I have this code:
import "./styles.css";
import "mvp.css";
import { useState } from "react";
import axios from "axios";
function Books() {
const [book, setBook] = useState("");
const [result, setResult] = useState([]);
const [apiKey, setApiKey] = useState(
""
);
function handleChange(event) {
const book = event.target.value;
setBook(book);
}
function handleSubmit(event) {
event.preventDefault();
axios
.get(
"https://www.googleapis.com/books/v1/volumes?q=" +
book +
"&key=" +
apiKey +
"&maxResults=20"
)
.then((data) => {
setResult(data.data.items);
})
.catch((error) => {
if (error.response) {
alert("No results found.");
} else if (error.request) {
alert("No results found.");
} else if (error.message) {
alert("No results found.");
}
});
}
return (
<div className="App">
<h1>Search For A Book</h1>
<form onSubmit={handleSubmit}>
<div className="form-group">
<input
type="text"
onChange={handleChange}
className="input"
placeholder="Search..."
/>
<button type="submit">Go!</button>
</div>
</form>
{result.map((book) => (
<a target="_blank" href={book.volumeInfo.previewLink}>
<img src={book.volumeInfo.imageLinks.thumbnail} alt={book.title} />
</a>
))}
</div>
);
}
export default function App() {
return <Books />;
}
And I am trying to do some error handling, and I get my alert messages as expected, however after I click off the alert box I get redirected to a typeerror that says:
book.volumeInfo.imageLinks is undefined
I am trying to suppress this and just go back to the default screen, but I am not sure how to accomplish this.
Firebase Phone number authentication not working. Upon submitting the form for entering the phone number, this is what the error shows: Google Sign in works but not the registration using Phone number.
Uncaught TypeError:
firebase_utils__WEBPACK_IMPORTED_MODULE_2_.auth.RecaptchaVerifier is not a function
import React, { useState, useEffect } from "react";
import { Button, TextField } from "#material-ui/core";
import { signInWithGoogle, firestore, auth } from "./../firebase/utils";
const Register = (props) => {
const [currentUser, setCurrentUser] = useState("");
const [displayName, setDisplayName] = useState("");
const [phoneNumber, setPhoneNumber] = useState("");
const [otp, setOtp] = useState("");
const getCurrentUser = () => {
auth.onAuthStateChanged((user) => {
if (user) {
const uid = user["uid"];
const name = user.displayName;
console.log("uid: ", uid);
console.log(name);
setCurrentUser(uid);
setDisplayName(name);
} else {
console.log("uid: ", "no uid");
}
});
};
useEffect(() => {
getCurrentUser();
}, []);
const configureCaptcha = () => {
window.recaptchaVerifier = auth.RecaptchaVerifier("sign-in-button", {
size: "invisible",
callback: (response) => {
// reCAPTCHA solved, allow signInWithPhoneNumber.
onSignInSubmit();
console.log("Verified");
},
defaultCountry: "PH",
});
};
const onSignInSubmit = (e) => {
e.preventDefault();
configureCaptcha();
const phoneNumber = phoneNumber;
console.log(phoneNumber);
const appVerifier = window.recaptchaVerifier;
auth
.signInWithPhoneNumber(phoneNumber, appVerifier)
.then((confirmationResult) => {
// SMS sent. Prompt user to type the code from the message, then sign the
// user in with confirmationResult.confirm(code).
window.confirmationResult = confirmationResult;
console.log("OTP has been sent");
// ...
})
.catch((error) => {
// Error; SMS not sent
// ...
console.log(error);
});
};
return (
<div>
<h1>Google SIGN IN</h1>
<Button variant="contained" onClick={signInWithGoogle}>
Google Sign In
</Button>
{auth.currentUser ? (
<div>
{" "}
<br />
UID: {currentUser}
<br />
Name: {displayName}
</div>
) : (
<div>
<h1>NOT LOGGED IN </h1>
<form onSubmit={onSignInSubmit}>
<div id="sign-in-button"></div>
<TextField
type="number"
name="mobile"
placeholder="mobile"
value={phoneNumber}
onChange={(e) => setPhoneNumber(e.target.value)}
/>
<Button type="submit">Submit</Button>
</form>
<h2>Enter OTP</h2>
<form>
<TextField
type="number"
name="OTP"
placeholder="Enter OTP"
value={otp}
onChange={(e) => setOtp(e.target.value)}
/>
<Button type="submit">Submit</Button>
</form>
</div>
)}
</div>
);
};
export default Register;
I doubt your code looks like this and that's incorrect:
const auth = firebase.auth()
window.recaptchaVerifier = auth.RecaptchaVerifier()
Try this instead
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier(...)
// ^^^^ not auth()
I got this code working pretty much how I want it. However, it's fetching & display data after each keystroke. I only want it to fetch once, when I hit submit.
Also, if there's anything i'm doing that's not "best practice" please let me know so I don't make silly mistakes in the future.
import React, { useEffect, useState } from "react";
export default function App() {
const [data, setData] = useState(null);
const [query, setQuery] = useState("");
useEffect(() => {
if (!query) return;
async function fetchData() {
const response = await fetch(
`https://www.omdbapi.com/?apikey=2e8b5857&s=${query}`
);
const data = await response.json();
const results = data.Search;
setData(results);
}
fetchData();
}, [query]);
const handleSubmit = (e) => {
e.preventDefault();
setQuery(query);
};
return (
<div
style={{
margin: 20,
}}
>
<form onSubmit={handleSubmit}>
<br />
<label>
Input Movie:{" "}
<input
type="text"
placeholder="ex. Harry Potter"
value={query}
onChange={(e) => {
setQuery(e.target.value);
}}
/>
</label>
<input type="submit" value="Submit" onClick={() => setQuery} />
</form>
{data &&
data.map((movie) => (
<div key={movie.imdbID}>
<h1>{movie.Title}</h1>
<h4>
{movie.Year} | {movie.imdbID}
</h4>
<img alt={movie.imdbID} src={`${movie.Poster}`} />
</div>
))}
</div>
);
}
Since you only want it after submit, you can skip the useEffect with [query] and just copy the same logic inside your handleSubmit like so :-
import React, { useEffect, useState } from "react";
export default function App() {
const [data, setData] = useState(null);
const [query, setQuery] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
if (!query) return;
async function fetchData() {
const response = await fetch(
`https://www.omdbapi.com/?apikey=2e8b5857&s=${query}`
);
const data = await response.json();
const results = data.Search;
setData(results);
}
fetchData();
};
return (
<div
style={{
margin: 20,
}}
>
<form onSubmit={handleSubmit}>
<br />
<label>
Input Movie:{" "}
<input
type="text"
placeholder="ex. Harry Potter"
value={query}
onChange={(e) => {
setQuery(e.target.value);
}}
/>
</label>
<input type="submit" value="Submit"/>
</form>
{data &&
data.map((movie) => (
<div key={movie.imdbID}>
<h1>{movie.Title}</h1>
<h4>
{movie.Year} | {movie.imdbID}
</h4>
<img alt={movie.imdbID} src={`${movie.Poster}`} />
</div>
))}
</div>
);
}
Here's the codesandbox :-
Pass the code that is inside the useEffect, that is, the fetch function, inside the submit function. leaving useEffect unused
I am following the serverless-stack.com tutorial. But I am stuck after creating the login button.
I keep getting the error:
Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
I don't know what is causing the render so many times.
I combined my LoaderButton instead of importing to make it simpler.
import React, { useState } from "react";
import { Auth } from "aws-amplify";
import { useHistory } from "react-router-dom";
import { FormGroup, FormControl, ControlLabel } from "react-bootstrap";
import { useFormFields } from "../libs/hooksLib";
import { onError } from "../libs/errorLib";
import "../css/index.css";
const LoaderButton = (
isLoading,
className = "",
disabled = false,
...props ) => {
return(
<Button
className={`LoaderButton ${className}`}
disabled={disabled || isLoading}
{...props}
>
{isLoading && <Glyphicon glyph="refresh" className="spinning" />}
{props.children}
</Button>
)
};
export default function Login() {
let history = useHistory();
const [isLoading, setIsLoading] = useState(false);
const [fields, handleFieldChange] = useFormFields({
email: "",
password: ""
});
function validateForm() {
return fields.email.length > 0 && fields.password.length > 0;
}
async function handleSubmit(event) {
event.preventDefault();
setIsLoading(true);
try {
await Auth.signIn(fields.email, fields.password);
userHasAuthenticated(true);
console.log(history);
//history.push("/");
} catch (e) {
onError(e);
setIsLoading(false);
}
}
return (
<div className="Login">
<form onSubmit={ () => { handleSubmit() } }>
<FormGroup controlId="email" bsSize="large">
<ControlLabel>Email</ControlLabel>
<FormControl
autoFocus
type="email"
value={fields.email}
onChange={ () => { handleFieldChange() } }
/>
</FormGroup>
<FormGroup controlId="password" bsSize="large">
<ControlLabel>Password</ControlLabel>
<FormControl
type="password"
value={fields.password}
onChange={ () => { handleFieldChange() } }
/>
</FormGroup>
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={ () => { isLoading() } }
disabled={() => { !validateForm() }}
>
Login
</LoaderButton>
</form>
</div>
);
}
hooksLib.js / useFormFields
import { useState } from 'react'
const useFormFields = (initalState) => {
const [fields, setValues] = useState(initalState)
return [
fields,
setValues({
...fields,
[event.target.id]: event.target.value
})
]
}
export { useFormFields }
Your custom hook should look like this if you want to accept the event value:
const useFormFields = (initalState) => {
const [fields, setValues] = useState(initalState)
return [
fields,
(event) => setValues({
...fields,
[event.target.id]: event.target.value
})
]
}
Since that parameter is actually a callback that should occur.
Also, your LoadingButton implementation needs to change to this:
<LoaderButton
block
type="submit"
bsSize="large"
isLoading={isLoading} // This is a boolean value, not a function
disabled={() => !validateForm()}
>...</LoaderButton>
Please note that I've already checked answers in this question and nothing seems to work.
I'm using this repo as a boilerplate. Instead of firebase database, I'm trying to send username and email with the firebase auth userid , to the node server. I created an action creator signup to handle this.
This is signup.js action creator
import * as types from '../constants/action_types';
import axios from 'axios';
export const signup = (user) => {
console.log(user);
return async dispatch => {
try {
const response = await axios.get('http://localhost:5000/api/user/register', user)
const data = await {response};
dispatch({
type : types.SIGN_UP,
payload : data.fromback
})
} catch (error) {
console.lot(error)
}
}
}
Then I've connected it with the component with mapDispatchToProps., So,under the SignUpPage component, React dev tools shows signup as a function. But when it get triggers, it gives an error saying _this2.props.signup is not a function Why's that ?
This is my SignUpPage component
import React, { Component } from 'react';
import {
Link,
withRouter,
} from 'react-router-dom';
import { auth } from '../../firebase';
import * as routes from '../../constants/routes';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import {signup} from './../../actions/signup';
const SignUpPage = ({ history }) =>
<div>
<h1>SignUp</h1>
<SignUpForm history={history} />
</div>
const updateByPropertyName = (propertyName, value) => () => ({
[propertyName]: value,
});
const INITIAL_STATE = {
username: '',
email: '',
passwordOne: '',
passwordTwo: '',
error: null,
};
class SignUpForm extends Component {
constructor(props) {
super(props);
this.state = { ...INITIAL_STATE };
}
onSubmit = (event) => {
const {
username,
email,
passwordOne,
} = this.state;
const {
history,
} = this.props;
auth.doCreateUserWithEmailAndPassword(email, passwordOne)
.then(authUser => {
const userid = authUser.user.uid;
const user = { email, userid };
this.props.signup(user);
})
.catch(error => {
this.setState(updateByPropertyName('error', error));
});
event.preventDefault();
}
render() {
const {
username,
email,
passwordOne,
passwordTwo,
error,
} = this.state;
const isInvalid =
passwordOne !== passwordTwo ||
passwordOne === '' ||
username === '' ||
email === '';
return (
<form onSubmit={this.onSubmit}>
<input
value={username}
onChange={event => this.setState(updateByPropertyName('username', event.target.value))}
type="text"
placeholder="Full Name"
/>
<input
value={email}
onChange={event => this.setState(updateByPropertyName('email', event.target.value))}
type="text"
placeholder="Email Address"
/>
<input
value={passwordOne}
onChange={event => this.setState(updateByPropertyName('passwordOne', event.target.value))}
type="password"
placeholder="Password"
/>
<input
value={passwordTwo}
onChange={event => this.setState(updateByPropertyName('passwordTwo', event.target.value))}
type="password"
placeholder="Confirm Password"
/>
<button disabled={isInvalid} type="submit">
Sign Up
</button>
{ error && <p>{error.message}</p> }
</form>
);
}
}
const SignUpLink = () =>
<p>
Don't have an account?
{' '}
<Link to={routes.SIGN_UP}>Sign Up</Link>
</p>
const mapDispatchToProps = dispatch => bindActionCreators({ signup }, dispatch)
export default connect(null, mapDispatchToProps)(withRouter(SignUpPage));
export {
SignUpForm,
SignUpLink,
};
Its not a prop,
you've imported it as a function,
you can directly use it as function like this
import {signup} from './../../actions/signup';
.....
auth.doCreateUserWithEmailAndPassword(email, passwordOne)
.then(authUser => {
const userid = authUser.user.uid;
const user = { email, userid };
signup(user);
})
.catch(error => {
this.setState(updateByPropertyName('error', error));
});