show login page for a second when routering other pages reactJS - html

I use this video https://www.youtube.com/watch?v=r4EsP6rovwk&t=1s to create an Auth for my website,
i basically copied his code the only change is that I route after successful login to different page.
the problem is that after login my home page is shown, but when I'm pressing buttons to route for other pages, before the other page is shown I see for a second the login page.
this is the code of the auth - I believe it connect to the problem (before this my website has worked well).
Edit:
i try to figure out what's the problem and I've noticed that when i'm using link everything's fine, but when using href there's a problem.
(And that's what I did in my website).
So... does anyone know why href makes this issue?
app.js
import React, { Component } from 'react';
import fire from './Fire';
import SearchAppBar from '../components/appBar';
import Login from './login';
class App extends Component {
constructor() {
super();
this.state = ({
user: null,
});
this.authListener = this.authListener.bind(this);
}
componentDidMount() {
this.authListener();
}
authListener() {
fire.auth().onAuthStateChanged((user) => {
if (user) {
this.setState({ user });
} else {
this.setState({ user: null });
}
});
}
render() {
return (
<div>{this.state.user ? ( <SearchAppBar/>) : (<Login />)}</div>)
}
}
export default App;
login.js:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import fire from './Fire';
class Login extends Component {
constructor(props) {
super(props);
this.login = this.login.bind(this);
this.handleChange = this.handleChange.bind(this);
this.signup = this.signup.bind(this);
this.state = {
email: '',
password: ''
};
}
handleChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
login(e) {
e.preventDefault();
fire.auth().signInWithEmailAndPassword(this.state.email, this.state.password).then((u)=>{
}).catch((error) => {
console.log(error);
});
}
signup(e){
e.preventDefault();
fire.auth().createUserWithEmailAndPassword(this.state.email, this.state.password).then((u)=>{
}).then((u)=>{console.log(u)})
.catch((error) => {
console.log(error);
})
}
render() {
return (
<div className="col-md-6">
<form>
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input value={this.state.email} onChange={this.handleChange} type="email" name="email"
class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter
email" />
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.
</small>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input value={this.state.password} onChange={this.handleChange} type="password" name="password"
class="form-control" id="exampleInputPassword1" placeholder="Password" />
</div>
<button type="submit" onClick={this.login} className="btn btn-primary">Login</button>
<button onClick={this.signup} style={{marginLeft: '25px'}} className="btn btn-
success">Signup</button>
</form>
</div>
);
}
}
export default Login;
Thank you all guys!!

Related

React - HTML form validation doesn't work

I work on a React project. I wrote HTML codes for create form. There is validation in HTML scripts. I wrote validations but validations doesn't work. The code is below. For example I want the relevant field to be red when the name is not entered or I want it to give a warning message when the name does not comply with the text rules. I must do it without any library. How can I fix it ?
import React, { Component } from 'react'
import EmployeeService from '../services/EmployeeService';
class CreateEmployeeComponent extends Component {
constructor(props) {
super(props)
this.state = {
id: this.props.match.params.id,
firstName: '',
lastName: '',
emailId: ''
}
}
componentDidMount(){
if(this.state.id === '_add'){
return
}else{
EmployeeService.getEmployeeById(this.state.id).then( (res) =>{
let employee = res.data;
this.setState({firstName: employee.firstName,
lastName: employee.lastName,
emailId : employee.emailId
});
});
}
}
saveOrUpdateEmployee = (e) => {
e.preventDefault();
let employee = {firstName: this.state.firstName, lastName: this.state.lastName, emailId: this.state.emailId};
console.log('employee => ' + JSON.stringify(employee));
// step 5
if(this.state.id === '_add'){
EmployeeService.createEmployee(employee).then(res =>{
this.props.history.push('/employees');
});
}else{
EmployeeService.updateEmployee(employee, this.state.id).then( res => {
this.props.history.push('/employees');
});
}
}
changeFirstNameHandler= (event) => {
this.setState({firstName: event.target.value});
}
changeLastNameHandler= (event) => {
this.setState({lastName: event.target.value});
}
changeEmailHandler= (event) => {
this.setState({emailId: event.target.value});
}
cancel(){
this.props.history.push('/employees');
}
getTitle(){
if(this.state.id === '_add'){
return <h3 className="text-center">Add Employee</h3>
}else{
return <h3 className="text-center">Update Employee</h3>
}
}
onSubmit = e => {
e.preventDefault();
}
render() {
return (
<div>
<br></br>
<div className = "container">
<div className = "row">
<div className = "card col-md-6 offset-md-3 offset-md-3">
{
this.getTitle()
}
<div className = "card-body">
<form onSubmit={this.onSubmit} noValidate>
<div className = "form-group">
<label for="validationCustom01" class="form-label">First name</label>
<input type='text' maxLength={20} pattern='[A-Za-z]' placeholder="First Name" name="firstName" className="form-control"
value={this.state.firstName} onChange={this.changeFirstNameHandler} required/>
</div>
<div className = "form-group">
<label> Last Name: </label>
<input type='text' maxLength={20} pattern='[A-Za-z]'class="form-control" placeholder="Last Name" name="lastName" className="form-control"
value={this.state.lastName} onChange={this.changeLastNameHandler} required/>
</div>
<div className = "form-group">
<label> Email Id: </label>
<input type='email' maxLength={35} pattern='[A-Za-z]' placeholder="Email Address" name="emailId" className="form-control"
value={this.state.emailId} onChange={this.changeEmailHandler} required/>
</div>
<button type="submit" className="btn btn-success" onClick={this.saveOrUpdateEmployee}>Save</button>
<button className="btn btn-danger" onClick={this.cancel.bind(this)} style={{marginLeft: "10px"}}>Cancel</button>
</form>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default CreateEmployeeComponent
Remove noValidate from your <form> element.
Additionally, I've personally found that Formik and Yup can be a helpful library.
(Sorry I missed that "no libraries" wasa constraint)
Edit:
I was a muppet and forgot to change the pattern
You can do one of 2 things:
Remove maxLength and change the pattern to pattern="[A-Za-z]{1,20}"
Where 20 will be the new max-length (so 20 or 35, depending on the field)
Only change the pattern to be pattern="[A-Za-z]+"
The + is needed to ensure 1 or more of the [A-Za-z] regex is done. https://regexr.com/
Also don't forget to remove noValidate from your <form> element.
This answer may also prove helpful in setting custom validity status messages and callbacks.

Pass Data between classes components (React)

I'm new to react and web dev in general. I need to pass a few values from a class to another when switching pages. My routes and links are working just fine.
I've tried a lot of stuff but I can't manage to pass the data to the class that is going to render the next page on the website. I need your help please ! (feel free to give me advice about the code, it's probably pretty shitty lol)
App.jsx
import React, { Component } from 'react'
import { BrowserRouter, Route, Routes} from 'react-router-dom';
import './App.css'
import SignIn from './SignIn/SignIn';
import Register from './Register/Register';
import Informations from './Register/Informations/Informations';
import PageNotFound from './PageNotFound/error';
import Photos from './Register/Informations/Photos/Photos'
class App extends Component {
render() {
return <BrowserRouter>
<Routes>
<Route path='/' element={<Register/>} exact/>
<Route path='/register' element={<Register/>}/>
<Route path='/sign-in' element={<SignIn/>}/>
<Route path='/infos' element={<Informations/>}/>
<Route path='/photos' element={<Photos/>}/>
<Route path='*' element={<PageNotFound/>}/>
</Routes>
</BrowserRouter>
}
}
export default App
Register.jsx (starting point of the site, I want the data to go from this class to the next one)
import React, { Component } from 'react';
import { Link } from "react-router-dom";
import './Register.scss'
import axios from 'axios'
import test_img from '../blink_logo.svg';
class Register extends Component
{
constructor (props) {
super(props);
this.state =
{
email: '',
firstname: '',
lastname: '',
telephone: '',
password: ''
}
this.handleLogin = this.handleLogin.bind(this);
}
handleLogin () {
axios.post('http://localhost:3000/api/user/', {email: this.state.email,
firstname: this.state.firstname,
lastname: this.state.lastname,
telephone: this.state.telephone,
password: this.state.password})
.then((response) =>
{
console.log(response);
this.setState({username: response.data.username})
}).catch(error =>
{
console.log(error);
})
console.log("Email: " + this.state.email);
console.log("Firstname: " + this.state.firstname);
console.log("Lastname: " + this.state.lastname);
console.log("Telephone: " + this.state.telephone);
console.log("Password: " + this.state.password);
}
handleEmailChange = (e) =>{
this.setState({email: e.target.value});
}
handleFirstnameChange = (e) =>{
this.setState({firstname: e.target.value});
}
handleLastnameChange = (e) =>{
this.setState({lastname: e.target.value});
}
handleTelephoneChange = (e) => {
this.setState({telephone: e.target.value});
}
handlePasswordChange = (e) => {
this.setState({password: e.target.value});
}
render () {
return (
<div>
<div className='image'>
< img src={test_img} alt="Blink Logo"/>
</div>
<div className='base-container-register'>
<div className='header'>Rejoindre l'aventure !</div>
<div className='content'>
<div className='form'>
<div className='label'>Email</div>
<div className='form-group'>
<input type="text" name="email" placeholder="email" value={this.state.email} onChange={this.handleEmailChange} />
</div>
<div className='label'>Prénom</div>
<div className='form-group'>
<input type="text" name="firstname" placeholder="prénom" value={this.state.firstname} onChange={this.handleFirstnameChange} />
</div>
<div className='label'>Nom</div>
<div className='form-group'>
<input type="text" name="lastname" placeholder="nom" value={this.state.lastname} onChange={this.handleLastnameChange} />
</div>
<div className='label'>Mot de passe</div>
<div className='form-group'>
<input type="password" name="password" placeholder="mot de passe" value={this.state.password} onChange={this.handlePasswordChange}/>
</div>
<div className='label'>Numéro de téléphone</div>
<div className='form-group'>
<input type="telephone" name="telephone" placeholder="numéro de téléphone" value={this.state.telephone} onChange={this.handleTelephoneChange}/>
</div>
</div>
<div className='footer' >
<Link to='/infos' state={{email: this.state.email}}>
<button onClick={this.handleLogin} className='footer'>Se lancer</button>
</Link>
{/* <Link to='/infos' params={email: this.state.email}>
<button onClick={this.handleLogin} className='footer'>Se lancer</button>
</Link> */}
</div>
</div>
</div>
<div className='redirect-to-signin'> Vous avez déjà un compte ? <Link to='/sign-in'>Sign in</Link> </div>
</div>
);
}
}
export default Register
Informations.jsx (where I want to grab the data from Register)
class Informations extends Component
{
constructor (props) {
super(props);
this.state =
{
username: '',
workInfo: '',
webSite: '',
socialId: '',
file: null,
file_name: '...'
}
this.handleLogin = this.handleLogin.bind(this);
this.handlePhotoChange = this.handlePhotoChange.bind(this)
}
I'm using react-router-dom v6.
Thank you in advance for your help.
When calling your Informations class just pass the values you want to send, as parameters.
<Informations value1={4} value2={8} />
To get the data you are sending from inside the Informations class:
this.props.value1
With v6 of react-router-dom, we can pass props to our components using the following method:
<Route path='/infos' element={<Informations value1={4} value2={8} />}/>
However, you are suggesting that values from the Register component need to make their way over to the Informations component. The better method for passing those values around would be to take advantage of React Context.
Using Context, you could have some state defined in a custom context that you can set in Register, and read in Informations.

Trying to add scroll event listener on window, but getting Uncaught TypeError: Cannot read property 'classList' of null

I am trying to add the bottom shadow to the search bar on scroll in react js. it is working well until I go on the second page of my app.
When I am trying to go on the second page, it showing
Uncaught TypeError: Cannot read property 'classList' of null
Not working code :
import React, { useEffect } from 'react';
import { AiOutlineSearch } from "react-icons/ai";
const SearchBar = ({ totalPrograms, programs, setPrograms }) => {
const handleScroll = () => {
if(window.scrollY) {
document.getElementById('sb-header').classList.add('h-shadow');
}
else {
document.getElementById('sb-header').classList.remove('h-shadow');
}
}
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => {window.removeEventListener('scroll', handleScroll)};
},[]);
const handleSubmit = (event) => {
event.preventDefault();
const searchProgramName = document.getElementById('search').value;
if(searchProgramName) {
setPrograms(
programs.filter(program =>
program.name.toLowerCase().includes(searchProgramName)
)
);
}
else {
handleClick();
}
}
const handleClick = () => {
const allPhase = document.getElementsByName('phase');
const checkedPhaseValue = [];
allPhase.forEach(phase => {
if(phase.checked) {
checkedPhaseValue.push(phase.value);
}
});
setPrograms(checkedPhaseValue.length ?
totalPrograms.filter(
program => checkedPhaseValue.includes(program.phase.toLowerCase())
)
: totalPrograms
);
}
return (
<header id='sb-header' className="container header-sb">
<form className="container container-center" onSubmit={handleSubmit}>
<div className="type-search">
<AiOutlineSearch className="icon"/>
<input id="search" type="search" placeholder="search by program name"/>
</div>
<div className="checkbox-container">
<div className="d-inline">
<input type="checkbox" onClick={handleClick} name="phase" id="open_application" value="application_open"/>
<label htmlFor="open_application">Open Application</label>
</div>
<div className="d-inline">
<input type="checkbox" onClick={handleClick} name="phase" id="application_in_review" value="application_review"/>
<label htmlFor="application_in_review">Application in Review</label>
</div>
<div className="d-inline">
<input type="checkbox" onClick={handleClick} name="phase" id="in_progress" value="in_progress"/>
<label htmlFor="in_progress">in Progress</label>
</div>
<div className="d-inline">
<input type="checkbox" onClick={handleClick} name="phase" id="completed" value="completed"/>
<label htmlFor="completed">Completed</label>
</div>
</div>
</form>
</header>
)
}
export default SearchBar;
On the second page, I am going by clicking on the Details button. Code for that :
import React from 'react';
import { Link } from 'react-router-dom';
import { FaAngleDoubleRight } from 'react-icons/fa';
import * as ROUTES from '../Constants/routes';
const ProgramCards = ({ program }) => {
return (
<div className="card">
<div className="card-header">
<h1 className="p-name">{program.name}</h1>
</div>
<div className="card-body">
<h3 className="p-category">{program.category}</h3>
<small className="p-phase">{(program.phase).replace('_', ' ')}</small>
<p className="p-description">{program.shortDescription}</p>
</div>
<div>
<div className="date-duration">
<small className="p-date">Start Date: {program.startDate}</small>
<small className="p-duration">Duration: {program.duration}</small>
</div>
<Link to={ROUTES.PROGRAM_DETAILS}>
<button className="card-button">
Details <FaAngleDoubleRight className="icon angled-icon" />
</button>
</Link>
</div>
</div>
)
}
export default ProgramCards;
My question is, why it is not working?
After this, I tried a different approach. And it is working well.
Working code :
import React, { useEffect, useState } from 'react';
import { AiOutlineSearch } from "react-icons/ai";
const SearchBar = ({ totalPrograms, programs, setPrograms }) => {
const [ scrolled, setScrolled ] = useState(false);
const handleScroll = () => {
if(window.scrollY > 10) {
setScrolled(true);
}
else {
setScrolled(false);
}
}
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => {window.removeEventListener('scroll', handleScroll)};
},[]);
const handleSubmit = (event) => {
event.preventDefault();
const searchProgramName = document.getElementById('search').value;
if(searchProgramName) {
setPrograms(
programs.filter(program =>
program.name.toLowerCase().includes(searchProgramName)
)
);
}
else {
handleClick();
}
}
const handleClick = () => {
const allPhase = document.getElementsByName('phase');
const checkedPhaseValue = [];
allPhase.forEach(phase => {
if(phase.checked) {
checkedPhaseValue.push(phase.value);
}
});
setPrograms(checkedPhaseValue.length ?
totalPrograms.filter(
program => checkedPhaseValue.includes(program.phase.toLowerCase())
)
: totalPrograms
);
}
return (
<header className={`container header-sb ${scrolled && 'h-shadow'}`}>
<form className="container container-center" onSubmit={handleSubmit}>
<div className="type-search">
<AiOutlineSearch className="icon"/>
<input id="search" type="search" placeholder="search by program name"/>
</div>
<div className="checkbox-container">
<div className="d-inline">
<input type="checkbox" onClick={handleClick} name="phase" id="open_application" value="application_open"/>
<label htmlFor="open_application">Open Application</label>
</div>
<div className="d-inline">
<input type="checkbox" onClick={handleClick} name="phase" id="application_in_review" value="application_review"/>
<label htmlFor="application_in_review">Application in Review</label>
</div>
<div className="d-inline">
<input type="checkbox" onClick={handleClick} name="phase" id="in_progress" value="in_progress"/>
<label htmlFor="in_progress">in Progress</label>
</div>
<div className="d-inline">
<input type="checkbox" onClick={handleClick} name="phase" id="completed" value="completed"/>
<label htmlFor="completed">Completed</label>
</div>
</div>
</form>
</header>
)
}
export default SearchBar;
Your second approach is the better and the react way to do it. It is generally discouraged to query the DOM managed by react yourself. Use ref's if you need the DOM node.
The first example is not working because handleScroll will be recreated every time the component re-renders. Therefore removing the listener will not remove the original listener as the function referenced by handleScroll has changed.
Therefore when your component unmounts the listener will not be removed correctly but react will remove the DOM node. Next time you scroll the handler will still be called but the node you are trying to query isn't there anymore.
You have to create the listener inside of useEffect so that your removeEventListener references the correct function:
useEffect(() => {
const handleScroll = () => setScrolled(window.scrollY > 10);
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
},[]);
Alternatively you could use useRef to create a stable reference to you listener function.

React js a problem about updating the state value [duplicate]

This question already has answers here:
Why does calling react setState method not mutate the state immediately?
(9 answers)
Closed 2 years ago.
i'am just a newbie at React , i'am trying to make a form , when submitting i call a function "handleSubmit" that saves all the information into the state, and then displaying it into a grid , but it wont work for some reasons .
i really do need your help : here is my code :
export default class products extends React.Component {
constructor() {
super();
this.handleSubmit = this.handleSubmit.bind(this);
this.state =
{
QrCode: ''
}
}
handleSubmit(event) {
event.preventDefault();
const data = new FormData(event.target);
data.set('username', data.get('username').toUpperCase());
this.setState({QrCode: data});
console.log(this.state);
}
render() {
return (
<div >
<div >
<form onSubmit={this.handleSubmit}>
<label htmlFor="username">Enter username</label>
<input id="username" name="username" type="text" />
<button>Send data!</button>
</form>
</div>
<div style={{margin: '10%', marginTop : '5%'}}>
<GridComponent dataSource={this.state} />
</div>
</div>
);
}
}
and here what i get :
i keep getting empty array
and thank you.
In React, you don't need use form to take values from inputs.
export default class App extends React.Component {
constructor() {
super();
this.state = {
userName: ""
};
}
render() {
return (
<div className="App">
<label htmlFor="username">Enter username</label>
<input
value={this.state.userName}
onChange={e => this.setState({ userName: e.target.value })}
name="username"
type="text"
/>
<button
onClick={() => {
alert(this.state.userName);
}}
>
Send data!
</button>
</div>
);
}
}
Hope it help you!

How to login validation using my api in React Js

React JS
I'm new to react js
In my api there is username and password. If the user login, have to validate from my json value
handleSubmit(e) {
fetch('https://randomuser.me/api?results=1')
.then((response) => {
return response.json()
.then((json) => {
if (response.ok) {
return Promise.resolve(json)
}
return Promise.reject(json)
})
})
alert(json) not working to check the result.
How can i fetch the username and password in the response?
And how to take this next page if the user was logged in successfully ?
My full Code
App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
const ReactCSSTG = CSSTransitionGroup;
class App extends Component {
constructor(props) {
super(props);
this.state = {
isVisible: true
}
// Bindings
this.handleSubmit = this.handleSubmit.bind(this);
this.handleRemount = this.handleRemount.bind(this);
}
handleSubmit(e) {
alert("dsa");
fetch('https://randomuser.me/api?results=1')
.then((response) => {
return response.json()
.then((json) => {
if (response.ok) {
return Promise.resolve(json)
}
return Promise.reject(json)
})
})
}
handleRemount(e) {
this.setState({
isVisible: true
}, function () {
console.log(this.state.isVisible)
});
e.preventDefault();
}
render() {
// const for React CSS transition declaration
let component = this.state.isVisible ? <Modal onSubmit={this.handleSubmit} key='modal' /> : <ModalBack onClick={this.handleRemount} key='bringitback' />;
return <ReactCSSTG transitionName="animation" transitionAppear={true} transitionAppearTimeout={500} transitionEnterTimeout={500} transitionLeaveTimeout={300}>
{component}
</ReactCSSTG>
}
}
// Modal
class Modal extends React.Component {
render() {
return <div className='Modal'>
<Logo />
<form onSubmit={this.props.onSubmit}>
<Input type='text' name='username' placeholder='username' />
<Input type='password' name='password' placeholder='password' />
<button> Sign In</button>
</form>
<a href='#'>Lost your password ?</a>
</div>
}
}
// Generic input field
class Input extends React.Component {
render() {
return <div className='Input'>
<input type={this.props.type} name={this.props.name} placeholder={this.props.placeholder} required />
<label htmlFor={this.props.name}></label>
</div>
}
}
// Fake logo
class Logo extends React.Component {
render() {
return <div className="logo">
<i><img src={logo} className="App-logo" alt="logo" /></i>
<span> Test </span>
</div>
}
}
// Button to brind the modal back
class ModalBack extends React.Component {
render() {
return (
<button className="bringitback" onClick={this.props.onClick} key={this.props.className}>Back to login page!</button>
);
}
}
export default App;
Thanks in Advance!
If you just want to catch data for now this will do the trick
fetch('https://randomuser.me/api?results=1')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(JSON.stringify(myJson));
});
fetch('https://randomuser.me/api?results=1')
.then((response) => {
// check for status code from service if success
// set response in state such as login success
this.route.navigate(['/']);
})
.catch(error =>{
console.log(error);
});
})
Taking user to next page. Use react router for achieving this.
Step 1: Wrap your <App /> inside <BrowserRouter />
Now validate response if username/password are correct using service call.
Then this.route.navigate(['/']);
This will navigate user to home page of app after successful login.
Heres What I did, keep in mind I set up my backend with express/node.
I used Axios to fetch from my api.
onSubmit = (e) => {
e.preventDefault();
axios.get('API_PATH')
.then(res => {
const user = res.data[0].username;
const password = res.data[0].password;
const username = this.state.username;
const passwordEntered = this.state.password;
if(username === '' && passwordEntered === ''){
document.getElementById('status').innerHTML = '<p>Please Enter A Valid Username and Password</p>';
}else if(user === username && passwordEntered === password){
document.getElementById('status').innerHTML = '';
console.log(user, password)
}else{
document.getElementById('status').innerHTML = '<p>Please Enter A Valid Username and Password</p>';
}
})
.catch(error => {
console.log(error);
});
}
Here is the form I used.
<Form
>
<Form.Row>
<Form.Group as={Col}>
<Form.Label>Username</Form.Label>
<Form.Control
type="text"
name="username"
id="username"
value={this.state.value}
onChange={this.handleChange}
>
</Form.Control>
</Form.Group>
<Form.Group as={Col}>
<Form.Label>Password</Form.Label>
<Form.Control
type="text"
id="password"
name="password"
value={this.state.value}
onChange={this.handleChange}
/>
</Form.Group>
</Form.Row>
<Button className="btn btn-sm btn-light" onClick={this.onSubmit}>
<i style={redColor} className="fas fa-sign-in-alt"></i> Login
</Button>
</Form>