Pass user id via props in React - reactjs

I'm new to React. I have App.jsx:
import React, { Component } from 'react';
import { Route, Switch } from 'react-router-dom';
import axios from 'axios';
import About from './components/About';
import NavBar from './components/NavBar';
import Form from './components/forms/Form';
import Logout from './components/Logout';
import UserStatus from './components/UserStatus';
import Seeds from './components/Seeds';
import Message from './components/Message';
class App extends Component {
constructor() {
super();
this.state = {
users: [],
title: 'Project',
isAuthenticated: false,
messageName: null,
messageType: null,
};
this.logoutUser = this.logoutUser.bind(this);
this.loginUser = this.loginUser.bind(this);
this.createMessage = this.createMessage.bind(this);
this.removeMessage = this.removeMessage.bind(this);
};
componentWillMount() {
if (window.localStorage.getItem('authToken')) {
this.setState({ isAuthenticated: true });
};
};
componentDidMount() {
this.getUsers();
};
getUsers() {
axios.get(`${process.env.REACT_APP_WEB_SERVICE_URL}/users`)
.then((res) => { this.setState({ users: res.data.data.users }); })
.catch((err) => { });
};
logoutUser() {
window.localStorage.clear();
this.setState({ isAuthenticated: false });
};
loginUser(token) {
window.localStorage.setItem('authToken', token);
this.setState({ isAuthenticated: true });
this.getUsers();
this.createMessage('Welcome', 'success');
};
createMessage(name='Sanity Check', type='success') {
this.setState({
messageName: name,
messageType: type
});
setTimeout(() => {
this.removeMessage();
}, 3000);
};
removeMessage() {
this.setState({
messageName: null,
messageType: null
});
};
render() {
return (
<div>
<NavBar
title={this.state.title}
isAuthenticated={this.state.isAuthenticated}
/>
<section className="section">
<div className="container">
{this.state.messageName && this.state.messageType &&
<Message
messageName={this.state.messageName}
messageType={this.state.messageType}
removeMessage={this.removeMessage}
/>
}
<div className="columns">
<div className="column is-half">
<br/>
<Switch>
<Route exact path='/' render={() => (
<SpotifyAuth
/>
)} />
<Route exact path='/about' component={About}/>
<Route exact path='/register' render={() => (
<Form
formType={'Register'}
isAuthenticated={this.state.isAuthenticated}
loginUser={this.loginUser}
createMessage={this.createMessage}
/>
)} />
<Route exact path='/login' render={() => (
<Form
formType={'Login'}
isAuthenticated={this.state.isAuthenticated}
loginUser={this.loginUser}
createMessage={this.createMessage}
/>
)} />
<Route exact path='/logout' render={() => (
<Logout
logoutUser={this.logoutUser}
isAuthenticated={this.state.isAuthenticated}
/>
)} />
<Route exact path='/status' render={() => (
<UserStatus
isAuthenticated={this.state.isAuthenticated}
/>
)} />
<Route exact path='/seeds' render={() => (
<Seeds
isAuthenticated={this.state.isAuthenticated}
/>
)} />
</Switch>
</div>
</div>
</div>
</section>
</div>
)
}
};
export default App;
this Form.jsx component:
import React, { Component } from 'react';
import axios from 'axios';
import { Redirect } from 'react-router-dom';
import { registerFormRules, loginFormRules, spotifyLoginFormRules } from './form-rules.js';
import FormErrors from './FormErrors.jsx';
class Form extends Component {
constructor (props) {
super(props);
this.state = {
formData: {
restaurant: '',
username: '',
email: '',
password: ''
},
registerFormRules: registerFormRules,
loginFormRules: loginFormRules,
valid: false,
};
this.handleUserFormSubmit = this.handleUserFormSubmit.bind(this);
componentDidMount() {
this.clearForm();
};
componentWillReceiveProps(nextProps) {
if (this.props.formType !== nextProps.formType) {
this.clearForm();
};
};
clearForm() {
this.setState({
formData: {restaurant: '', username: '', email: '', password: ''}
});
};
handleFormChange(event) {
const obj = this.state.formData;
obj[event.target.name] = event.target.value;
this.setState(obj);
this.validateForm();
};
handleUserFormSubmit(event) {
event.preventDefault();
const formType = this.props.formType
const data = {
restaurant: this.state.formData.restaurant,
email: this.state.formData.email,
password: this.state.formData.password
};
if (formType === 'Register') {
data.username = this.state.formData.username
};
const url = `${process.env.REACT_APP_WEB_SERVICE_URL}/auth/${formType.toLowerCase()}`;
axios.post(url, data)
.then((res) => {
this.clearForm();
this.props.loginUser(res.data.auth_token);
})
.catch((err) => {
if (formType === 'Login') {
this.props.createMessage('Login failed.', 'danger');
};
if (formType === 'Register') {
this.props.createMessage('That user already exists.', 'danger');
};
});
};
allTrue() {
let formRules = loginFormRules;
if (this.props.formType === 'Register') {
formRules = registerFormRules;
}
for (const rule of formRules) {
if (!rule.valid) return false;
}
return true;
};
resetRules() {
const registerFormRules = this.state.registerFormRules;
for (const rule of registerFormRules) {
rule.valid = false;
}
this.setState({registerFormRules: registerFormRules})
const loginFormRules = this.state.loginFormRules;
for (const rule of loginFormRules) {
rule.valid = false;
}
this.setState({loginFormRules: loginFormRules})
};
validateEmail(email) {
// eslint-disable-next-line
var re = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
};
render() {
if (this.props.isAuthenticated) {
return (<Redirect to='/' />);
};
let formRules = this.state.loginFormRules;
if (this.props.formType === 'Register') {
formRules = this.state.registerFormRules;
}
return (
<div>
{this.props.formType === 'Login' &&
<h1 className="title is-1">Log In</h1>
}
{this.props.formType === 'Register' &&
<h1 className="title is-1">Register</h1>
}
<hr/><br/>
<FormErrors
formType={this.props.formType}
formRules={formRules}
/>
<form onSubmit={(event) => this.handleUserFormSubmit(event)}>
{this.props.formType === 'Register' &&
<div className="field">
<input
name="restaurant"
className="input is-medium"
type="text"
placeholder="Enter your restaurant name"
required
value={this.state.formData.coffeeshop}
onChange={this.handleFormChange}
/>
</div>
}
<div className="field">
<input
name="username"
className="input is-medium"
type="text"
placeholder="Enter a username"
required
value={this.state.formData.username}
onChange={this.handleFormChange}
/>
</div>
<div className="field">
<input
name="email"
className="input is-medium"
type="email"
placeholder="Enter an email address"
required
value={this.state.formData.email}
onChange={this.handleFormChange}
/>
</div>
<div className="field">
<input
name="password"
className="input is-medium"
type="password"
placeholder="Enter a password"
required
value={this.state.formData.password}
onChange={this.handleFormChange}
/>
</div>
<input
type="submit"
className="button is-primary is-medium is-fullwidth"
value="Submit"
disabled={!this.state.valid}
/>
</form>
</div>
)
};
};
export default Form;
and UserStatus.jsx
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import './css/box.css'
class UserStatus extends Component {
constructor (props) {
super(props);
this.state = {
restaurant:'',
email: '',
id: '',
username: '',
active: '',
admin: ''
};
};
componentDidMount() {
if (this.props.isAuthenticated) {
this.getUserStatus();
}
};
getUserStatus(event) {
const options = {
url: `${process.env.REACT_APP_WEB_SERVICE_URL}/auth/status`,
method: 'get',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${window.localStorage.authToken}`
}
};
return axios(options)
.then((res) => {
console.log(res.data)
console.log(res.data.data)
this.setState({
restaurant: res.data.data.restaurant,
email: res.data.data.email,
id: res.data.data.id,
username: res.data.data.username,
active: String(res.data.data.active),
admin: String(res.data.data.admin),
})
})
.catch((error) => { console.log(error); });
};
render() {
if (!this.props.isAuthenticated) {
return (
<p>You must be logged in to view this. Click <Link to="/login">here</Link> to log back in.</p>
)
};
return (
<div>
<h1 className="title is-1"><font color="#C86428">Current User</font></h1>
<hr/><br/>
<ul>
<li><strong><font color="#C86428">restaurant:</font></strong><font color="white"> {this.state.restaurant} </font></li>
<li><strong><font color="#C86428">User ID:</font></strong><font color="white"> {this.state.id} </font></li>
<li><strong><font color="#C86428">Email:</font></strong><font color="white"> {this.state.email} </font></li>
<li><strong><font color="#C86428">Username:</font></strong><font color="white"> {this.state.username} </font></li>
<li><strong><font color="#C86428">Active:</font></strong><font color="white"> {this.state.active} </font></li>
<li><strong><font color="#C86428">Admin:</font></strong><font color="white"> {this.state.admin} </font></li>
</ul>
</div>
)
};
};
export default UserStatus;
finally, this Seeds.jsx, where I need user.id in order to call my backend, like so:
import React, { Component } from 'react';
import axios from 'axios';
class Seeds extends Component{
constructor (props) {
super(props);
this.state = {
restaurant:'',
email: '',
id: '',
username: '',
active: '',
admin: '',
template:'',
formSeeds:{
type1:'',
type2:'',
type3:'',
},
formEditMenu:{
item:'',
item2:'',
item3:'',
}
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmitSeeds = this.handleSubmitSeeds.bind(this);
this.handleSubmitCoffees = this.handleSubmitCoffees.bind(this);
};
componentDidMount() {
if (this.props.isAuthenticated) {
this.getSeeds();
}
};
getSeeds(event) {
const options = {
url: `${process.env.REACT_APP_WEB_SERVICE_URL}/seeds/${this.props.getUserStatus.id}`, //HERE
method: 'get',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${window.localStorage.authToken}`
}
};
return axios(options)
.then((res) => {
console.log(res.data.data)
this.setState({
restaurant: res.data.data[0].restaurant,
id: res.data.data[0].id,
template: res.data.data[0].content
})
console.log(res.data.data[0].id);
})
.catch((error) => { console.log(error); });
};
handleChange(event){
const objformSeeds = this.state.formSeeds;
objformSeeds[event.target.name] = event.target.value;
this.setState(objformSeeds);
const formEditMenu = this.state.formEditMenu;
formEditMenu[event.target.name] = event.target.value;
this.setState(formEditMenu);
}
handleSubmitSeeds(event) {
event.preventDefault();
//const formSeeds = this.props.formSeeds
const data = {
type1: this.state.formSeeds.type1,
type2: this.state.formSeeds.type2,
type3: this.state.formSeeds.type3,
};
const url = `${process.env.REACT_APP_WEB_SERVICE_URL}/handle_seeds`;
axios.post(url, data)
.then((res) => {
console.log(data);
})
.catch((err) => {
});
};
handleSubmitCoffees(event) {
event.preventDefault();
//const formEditMenu = this.props.formEditMenu
const data = {
item: this.state.formEditMenu.item,
item2: this.state.formEditMenu.item2,
item3: this.state.formEditMenu.item3,
};
const url = `${process.env.REACT_APP_WEB_SERVICE_URL}/edit_menu${this.props.getUserStatus.id}`; //AND HERE
axios.post(url, data)
.then((res) => {
console.log(data);
})
.catch((err) => {
});
};
render(){
//var seeds_page = this.state.template;
var __html = this.state.template;
var template = { __html: __html };
return (
<div id="parent">
<div dangerouslySetInnerHTML={template}/>
<form>
<input type='text' name='name' onChange={this.handleChange}/><br/>
<button type="button" onClick={this.handleSubmitCoffees} />
</form>
</div>
);
}
}
export default Seeds;
I am trying to get id via props (this.props.getUserStatus.id), but I get undefined. How do I pass my user.id to Seeds.jsx component here?

Well, first of all you may want to use a store like redux for state management. If you really want to keep your state locally, then you should "lift it", and move your getUserStatus() function in the highest possible parent (in your case App.js). In your App.js you then set a userStatus object in the state and pass it down to all components which need it.
<Route exact path='/seed' render={() => (
<Seed
....
userStatus={this.state.userStatus}
/>
)} />
and in your child component:
....
render(){
const { userStatus } = this.props
return(
......
const url = `${process.env.REACT_APP_WEB_SERVICE_URL}/edit_menu${userStatus.id}`;
)
}

The only property you passed to Seeds is isAuthenticated.

Related

Redirect to dashboard page after login not working in React

I am trying to register and login through React via APIs using CORS. Registration of user done with email and password now I'm trying to login with email and password from login page (http://localhost:3000/login). I have to redirect to dashboard after login (http://localhost:3000/dashboard).
When I try to do this I'm getting error in console:
login error TypeError: _this2.props.handleSuccessfullAuth is not a function
at Login.js
Below is my error screenshot:
I'm a beginner in React.
My login file in components/auth/Login.js:
import React, { Component } from "react";
import axios from "axios";
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
loginErrors: ""
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
handleSubmit(event) {
const { email, password } = this.state;
axios
.post(
"http://localhost:3001/sessions",
{
user: {
email: email,
password: password
}
},
{ withCredentials: true }
)
.then(response => {
if (response.data.status === "created") {
this.props.handleSuccessfullAuth(response.data);
}
})
.catch(error => {
console.log("login error", error);
});
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input className="input-signin-data"
type="email" value={this.state.email}
onChange={this.handleChange}
required name="email"
placeholder ="Email or phone number"
/>
<br/>
<input className="input-signin-data"
type="password" value={this.state.password}
onChange={this.handleChange}
required name ="password"
placeholder ="Password"
/>
<br/>
<button type="submit" className="btn btn-secondary border-signin-btn-search" >Signin</button>
</form>
);
}
}
app.js file in components/App.js
import React, { Component } from "react";
import axios from "axios";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import { Navbar} from 'react-bootstrap';
import { Button} from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import Dashboard from "./Dashboard";
import Login from "./auth/Login";
import Signup from "./auth/Signup";
export default class App extends Component {
constructor() {
super();
this.state = {
loggedInStatus: "NOT_LOGGED_IN",
user: {}
};
this.handleLogin = this.handleLogin.bind(this);
this.handleLogout = this.handleLogout.bind(this);
this.handleSuccessfulAuth = this.handleSuccessfulAuth.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
}
handleSuccessfulAuth(data) {
this.props.handleLogin(data);
this.props.history.push("/dashboard");
}
handleLogoutClick() {
axios
.delete("http://localhost:3001/logout", { withCredentials: true })
.then(response => {
this.props.handleLogout();
})
.catch(error => {
console.log("logout error", error);
});
}
checkLoginStatus() {
axios
.get("http://localhost:3001/logged_in", { withCredentials: true })
.then(response => {
if (
response.data.logged_in &&
this.state.loggedInStatus === "NOT_LOGGED_IN"
) {
this.setState({
loggedInStatus: "LOGGED_IN",
user: response.data.user
});
} else if (
!response.data.logged_in &
(this.state.loggedInStatus === "LOGGED_IN")
) {
this.setState({
loggedInStatus: "NOT_LOGGED_IN",
user: {}
});
}
})
.catch(error => {
console.log("check login error", error);
});
}
componentDidMount() {
this.checkLoginStatus();
}
handleLogout() {
this.setState({
loggedInStatus: "NOT_LOGGED_IN",
user: {}
});
}
handleLogin(data) {
this.setState({
loggedInStatus: "LOGGED_IN",
user: data.user
});
}
render() {
return (
<div className="container-fluid app-container">
<Router>
<div className="container-fluid main-conatiner">
<Navbar>
<Navbar.Brand className="brand1" >
<Link to="/"><Button className="border-btn" >Jobsenlist</Button></Link>
</Navbar.Brand>
<Navbar.Toggle />
<Navbar.Collapse className="justify-content-end">
<Navbar.Text className="brand2">
<Link to="/login"><Button className="border-btn mr-3" >Signin </Button></Link>
<Link to="/signup"><Button className="border-btn " > Signup</Button></Link>
</Navbar.Text>
</Navbar.Collapse>
</Navbar>
<Switch>
<Route path="/login"><Login /></Route>
<Route path="/signup">
<Signup />
</Route>
</Switch>
<p>Status: {this.props.loggedInStatus}</p>
<button onClick={() => this.handleLogoutClick()}>Logout</button>
</div>
</Router>
</div>
);
}
}
Dashboard file in components/Dashboard.js
import React from "react";
const Dashboard = props => {
return (
<div>
<div>
<h1>Dashboard</h1>
<h1>Status: {props.loggedInStatus}</h1>
</div>
</div>
);
};
export default Dashboard;
You're not calling your function properly.
You're calling this.props.handleLogin(data) while your function is in the same component.
You should do this.handleLogin(data)

How to redirect to a another page in reactjs when switch case statement is executed?

I want to know how to make a redirection after a case statement. I have been making this code, but after the case statement, nothing happens. I review on the web, but nothing seems to work.When i submit the validated form, it doesn't redirect or refreshes.
Code
import { Redirect } from 'react-router-dom'
import React, { Component } from 'react'
const initState = {}
const adReducer = (state = initState, action) => {
switch (action.type) {
case 'CREATE_AD_SUCCESS':
alert('create ad success');
return <Redirect to='/' /> ;
case 'CREATE_AD_ERROR':
alert('create ad error');
return state;
default:
return state;
}
};
export default adReducer;
adAction.js code
export const createAd = (ad) => {
return (dispatch, getState, {getFirebase,getFirestore}) => {
// make async call to database
const firestore = getFirestore();
const profile = getState().firebase.profile;
const authorId = getState().firebase.auth.uid;
firestore.collection('ads').add({
...ad,
authorFirstName: profile.firstName,
authorLastName: profile.lastName,
authorId: authorId,
createdAt: new Date()
}).then(() => {
dispatch({ type: 'CREATE_AD_SUCCESS' });
}).catch(err => {
dispatch({ type: 'CREATE_AD_ERROR' }, err);
});
}
};
Create ad code :
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { createAd } from '../../store/actions/adActions'
import { Redirect } from 'react-router-dom'
import firebase from "firebase";
import FileUploader from "react-firebase-file-uploader";
class CreateAd extends Component {
state = {
title: '',
content: '',
avatar: "",
isUploading: false,
progress: 0,
avatarURL: "",
contactno:""
}
handleChange = (e) => {
this.setState({
[e.target.id]: e.target.value
})
}
handleSubmit = (e) => {
e.preventDefault();
this.props.createAd(this.state);
}
handleUploadStart = () => this.setState({ isUploading: true, progress: 0 });
handleProgress = progress => this.setState({ progress });
handleUploadError = error => {
this.setState({ isUploading: false });
console.error(error);
};
handleUploadSuccess = filename => {
this.setState({ avatar: filename, progress: 100, isUploading: false });
firebase
.storage()
.ref("images")
.child(filename)
.getDownloadURL()
.then(url => this.setState({ avatarURL: url }));
};
render() {
const { auth } = this.props;
if (!auth.uid) return <Redirect to='/signin' />
return (
<div className="container">
<form className="white" onSubmit={this.handleSubmit}>
<h5 className="grey-text text-darken-3">Create a New Ad</h5>
<div className="input-field">
<input type="text" id='title' onChange={this.handleChange} />
<label htmlFor="title">Ad Title</label>
</div>
<div className="input-field">
<textarea id="content" className="materialize-textarea" onChange={this.handleChange}></textarea>
<label htmlFor="content">AdContent</label>
</div>
<div className="input-field">
<input type="text" id='contactno' onChange={this.handleChange} />
<label htmlFor="title">Contact Number</label>
</div>
{ this.state.progress==100? <div class="col-md-4">
<img class="responsive-img" src={this.state.avatarURL}></img>
</div>:""}
<br/>
<label style={{backgroundColor: 'steelblue', color: 'white', padding: 10, borderRadius: 4, pointer: 'cursor'}}>
Upload a photo
{/* {this.state.isUploading && <p>Progress: {this.state.progress}</p>}
{this.state.avatarURL && <img src={this.state.avatarURL} />} */}
<FileUploader
hidden
accept="image/*"
storageRef={firebase.storage().ref('images')}
onUploadStart={this.handleUploadStart}
onUploadError={this.handleUploadError}
onUploadSuccess={this.handleUploadSuccess}
onProgress={this.handleProgress}
/>
</label>
<div className="input-field">
<button className="btn pink lighten-1">Create</button>
</div>
</form>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
auth: state.firebase.auth
}
}
const mapDispatchToProps = dispatch => {
return {
createAd: (ad) => dispatch(createAd(ad))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(CreateAd)
These are my codes.
You should use return window.location.replace("/") instead of return <Redirect to="/" />.
"React Router Redirect" redirects from A to B, for example <Redirect from="/about" to="/" />

When login button is clicked the page is Redirecting but not rendering the page

In user login form I am when I click login button it gives a token.
I am setting up the token in local storage and redirecting to 'customers' page.The page gets redirected to 'customers' but the page is not rendered.I have added a console.log in customer Page to check the whether the page is rendering or not.In this case it is not rendering it.
LoginForm
import React from 'react';
import _ from 'lodash';
import axios from '../config/Axios';
class LoginForm extends React.Component {
constructor() {
super()
this.state = {
email: '',
password: '',
error: '',
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(e) {
this.setState({
[e.target.name]: e.target.value
})
}
handleSubmit(e) {
e.preventDefault()
const loginData = {
email: this.state.email,
password: this.state.password,
}
axios.post('/users/login', loginData, {
headers: {
'x-auth': localStorage.getItem('token')
}
})
.then((response) => {
console.log(response.data)
if (response.data.error) {
const error = response.data.error
this.setState({ error })
}
else {
const token = response.data.token
localStorage.setItem('token', token);
this.props.history.push('/customers')
}
})
.catch(err => console.log(err))
}
render() {
return (
<div className="form-group container">
<h1>Login</h1>
<form onSubmit={this.handleSubmit}>
<br />
<label htmlFor="email-login">Email</label>
<br />
<input type="email" value={this.state.email} onChange={this.handleChange} name="email" id="email-login" />
<br />
<label htmlFor="password-login">Password</label>
<br />
<input type="password" value={this.state.password} onChange={this.handleChange} name="password" id="password-login" />
<br />
<button type="submit" className="btn btn-info">Login</button>
{
!_.isEmpty(this.state.error) && <h3>{this.state.error}</h3>
}
</form>
</div>
)
}
}
export default LoginForm
Customer Page
class CustomerList extends React.Component {
constructor() {
super()
this.state = {
customers: [],
isLoading: true,
}
this.handleChange = this.handleChange.bind(this)
this.handleSave = this.handleSave.bind(this)
}
componentDidMount() {
axios.get('/customers', {
headers: {
'x-auth': localStorage.getItem('token')
}
})
.then(response => {
console.log(response.data)
const customers = response.data
this.setState({ customers, isLoading: false })
return customers
})
.catch(err => console.log(err))
}
handleChange(text) {
console.log(this.state.customers)
const customerDatas = this.state.customers
const customers = customerDatas.filter((customerData => {
return customerData.name.toLowerCase().includes(text)
}))
if (this.state.customers.length) {
this.setState({ customers })
}
else {
console.log(`${customers}......`)
this.componentDidMount()
}
}
render() {
console.log('customer localStorage', localStorage)
return (
<div>
<br />
<SearchBox handleChange={this.handleChange} />
<br />
{this.state.isLoading ? (
<Loader />
) : (
<div>
<h3>Progress Bar</h3>
</div>
)}
<br />
</div>
)
}
}
export default CustomerList
As discussed in chat and comments - you did not have router added in your Router Component
Please add the below line
<Route path='/customers' exact={true} component={CustomerList} />
check what the this.props what will be shown is that content history or not undefined
and do you have a router to element

React js PrivateRoute show hide a dashboard Component based on JSON web token and fetch call

I need help when a user go to the URL http://localhost:3000/dashboard
if the admin already logged in before he will be able to see the Dashboard we just verify the token in his local-storage? i verify that JSON web token by sending it to the node.js app verify it if its good we send 200 status and if its bad token we send 401 status and based on the status we set the Private Route to show true or false, the fetch function its ready but i cant find a way to integrate it
this is the app files structure
my-app/
README.md
node_modules/
package.json
public/
index.html
favicon.ico
src/
|components/
|Clien/
|Home.js
|Home.css
|Header.js
|Footer.js
|admin/
|Auth.js
|PrivateRoute.js
|Admin.js
|Dashboard.js
|Dashboard.css
App.css
App.js
index.css
index.js
logo.svg
this is the function I use to check for JWT in local storage and verify the token sending it to the server get back the res and based on the response I wanna show the dashboard or redirect to Admin login form
right now everything works fine but only if I change the isAuthenticated (in Auth Class) manually I can't find a way to do the verification based on the fetch answer from the server,
I'm not sure if I should use the function in the Auth class as a function or should I create a Component with a state and componentDidMount()
please guide me as I'm a beginner:
this is the function
componentDidMount(){
//get token from local storage if there is one
const jwttoken = localStorage.getItem('jwttoken');
const bearer = 'Bearer '+ jwttoken;
const data = new FormData();
// get the website backend main url from .env
const REACT_APP_URL = process.env.REACT_APP_URL
fetch(`${REACT_APP_URL}/api/auth/verify`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': bearer,
},
body: data
}).then( (res)=> {
if (res.status === 401) {
res.json()
.then( (res)=> {
this.setState({
isLogedout: true,
})
localStorage.removeItem('jwttoken');
})
} else if (res.status === 200) {
res.json()
.then((res)=> {
this.setState({
isLogedout: false,
adminEmail: res.adminEmail
})
this.props.history.push("/dashboard");
})
}else{
this.setState({
isLogedout: true,
})
localStorage.removeItem('jwttoken');
}
}).catch((err) => {
// console.log(err)
})
}
this is the App Component where all routes are
import React, { Component } from "react";
import { Route, } from "react-router-dom";
// import Auth from "./Components/Admin/Auth"
import logo from "./Components/img/logo.jpg";
import headerimg from "./Components/img/header.png";
import "./App.css";
import Home from "./Components/Home";
import Dashboard from "./Components/Admin/Dashboard";
import Articles from "./Components/Articles";
import ArticleId from "./Components/ArticleId";
import Admin from "./Components/Admin/Admin.js";
import{ PrivateRoute} from "./Components/Admin/PrivateRoute.js";
class App extends Component {
constructor(props, context) {
super(props, context);
this.state = {
webiste: {
title: "Website title",
headerimg: headerimg,
altheaderimg: "website header image",
logo: logo,
logotitle: "website logo "
},
};
}
render() {
return (
<div className="app-container">
<Route exact path='/' render={(props) => <Home {...props} setTab={"home"} />} />
<Route exact path='/home' render={(props) => <Home {...props} setTab={"home"} />} />
<Route path='/articles' render={(props) => <Articles {...props} setArticle={"false"} />} />
<Route path='/article/:id' render={(props) => <ArticleId {...props.match.params} setArticle={"false"} />} />
<Route exact path='/services' render={(props) => <Home {...props} setTab={"services"} />} />
<Route exact path='/events' render={(props) => <Home {...props} setTab={"events"} />} />
<Route exact path='/about' render={(props) => <Home {...props} setTab={"about"} />} />
<Route exact path='/contact' render={(props) => <Home {...props} setTab={"contact"} />} />
<Route exact path='/admin' component={Admin} />
<PrivateRoute exact path="/dashboard" component={Dashboard} />
</div>
);
}
}
export default App;
this is the:
PrivateRoute Component
import React, { Component } from "react";
import { Route, Redirect, } from "react-router-dom";
import Auth from "./Auth"
export const PrivateRoute = ({ component: Component, ...rest }) => {
return (
<Route {...rest} render={(props) => (
Auth.isAuthenticated() === true
? <Component {...props} />
: <Redirect to='/admin' />
)} />
)
}
this is the:
Auth class
class Auth {
constructor() {
this.authenticated = true;
}
login(cb) {
this.authenticated = true;
cb();
}
logout(cb) {
this.authenticated = false;
cb();
}
isAuthenticated() {
return this.authenticated;
}
}
export default new Auth();
this is the:
Dashboard Component sorry its huge so I'm not including everything what it matters for me how to show and hide it in the PrivateRouter
class Dashboard extends Component {
constructor(props) {
super(props);
this.state = {
Articles: true,
AddArticles: false,
Messages: false,
Services: false,
Events: false,
About: false,
AdminContact: false,
AdminAddEvent: false,
WebsiteInfo: false,
isLogedin: '',
//dynamic className
classArticles: "admin-side-bar-button-selected",
classAddArticle: "admin-side-bar-button",
classEvents: "admin-side-bar-button",
classAddEvents: "admin-side-bar-button",
classServices: "admin-side-bar-button",
classAbout: "admin-side-bar-button",
classContact: "admin-side-bar-button",
classWebsiteInfo: "admin-side-bar-button",
};
}
render() {
return (
<div>
< div key="1" className="all-dashboard-container" >
<div className="header-dashboard">
<AdminHeader logout={this.logout} />
</div>
<div className="dashboard-container">
<div className="side-dashboard">
<button className={this.state.classArticles} onClick={this.showArticles}>Articles</button>
<div className="hr"></div>
<button className={this.state.classAddArticle} onClick={this.showAddArticles}>Add Aricle</button>
<div className="hr"></div>
<button className={this.state.classEvents} onClick={this.showEvents}>Events </button>
<div className="hr"></div>
<button className={this.state.classAddEvents} onClick={this.showAdminAddEvent}>Add Events</button>
<div className="hr"></div>
<button className={this.state.classServices} onClick={this.showServices}>Services </button>
<div className="hr"></div>
<button className={this.state.classAbout} onClick={this.showAbout}>About </button>
<div className="hr"></div>
<button className={this.state.classContact} onClick={this.showContact}>Contact</button>
<div className="hr"></div>
<button className={this.state.classWebsiteInfo} onClick={this.showWebsiteInfo}>Website Info </button>
<div className="hr"></div>
</div>
<div className="body-dashboard">
<div>
<div>
{this.state.Articles && <div> <AdminPublishedArticles /> </div>}
</div>
<div>
{this.state.AddArticles && <div> <AdminAddArticle /> </div>}
</div>
<div>
{this.state.AdminAddEvent && <div> <AdminAddEvent /> </div>}
</div>
<div>
{this.state.Events && <div> <AdminPublishedEvents /> </div>}
</div>
<div>
{this.state.Services && <div> <AdminServices /> </div>}
</div>
<div>
{this.state.About && <div> <AdminAbout /> </div>}
</div>
<div>
{this.state.AdminContact && <div> <AdminContact/> </div>}
</div>
<div>
{this.state.WebsiteInfo && <div> <WebsiteInfo /> </div>}
</div>
</div>
</div>
</div>
<div> <Footer/></div>
</div>
</div>
);
}
}
export default Dashboard;
this is the Admin Component its a login form
import React, { Component } from 'react';
import "./css/Admin.css";
import Auth from './Auth';
class Admin extends Component {
constructor(props) {
super(props);
this.state = {
adminEmail: '',
password: '',
loginError: false,
isLogedout: null
}
}
componentDidMount(){
//get token from local storage if there is one
const jwttoken = localStorage.getItem('jwttoken');
const bearer = 'Bearer '+ jwttoken;
const data = new FormData();
// get the website backend main url from .env
const REACT_APP_URL = process.env.REACT_APP_URL
fetch(`${REACT_APP_URL}/api/auth/verify`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': bearer,
},
body: data
}).then( (res)=> {
if (res.status === 401) {
res.json()
.then( (res)=> {
this.setState({
isLogedout: true,
adminEmail: res.adminEmail
})
localStorage.removeItem('jwttoken');
})
} else if (res.status === 200) {
res.json()
.then((res)=> {
this.setState({
isLogedout: false,
adminEmail: res.adminEmail
})
this.props.history.push("/dashboard");
})
}else{
this.setState({
isLogedout: true,
adminEmail: res.adminEmail
})
localStorage.removeItem('jwttoken');
}
}).catch((err) => {
// console.log(err)
})
}
handleSubmit = (event) => {
event.preventDefault();
const data = new FormData();
data.append('email', this.state.email);
data.append('password', this.state.password);
// get the website backend main url from .env
const REACT_APP_URL = process.env.REACT_APP_URL
fetch(`${REACT_APP_URL}/api/auth/login`, {
method: 'POST',
headers: {
'Accept': 'application/json',
// 'Content-Type': 'application/x-www-form-urlencoded'
},
body: data
}).then( (response)=> {
if (response.status === 401) {
response.json()
.then( (res)=> {
console.log(res)
this.setState({ loginError: true })
})
} else if (response.status === 200) {
response.json()
.then((res) => {localStorage.setItem('jwttoken', res) })
.then((res)=> {
Auth.login(()=>{
this.props.history.push("/dashboard");
})
})
}
}).catch((err) => {
err.json()
.then(console.log(err))
})
}
changeEventEmail = (event) => {
this.setState({
email: event.target.value,
loginError: false
});
}
changeEventPassword = (event) => {
this.setState({
password: event.target.value,
loginError: false
});
}
render() {
return (
<div>
{ this.state.isLogedout &&
<div className="admin-login-container">
<form className="admin-login-form" onSubmit={this.handleSubmit}>
<label>Email</label>
<input type="text" onChange={this.changeEventEmail} value={this.state.email} required />
<label >Password </label>
<input type="text" onChange={this.changeEventPassword} value={this.state.password} required />
<input className="admin-login-submit" type="submit" value="Login" />
</form>
{ this.state.loginError &&
<div className="admin-login-err">wrong email or password</div>
}
</div> }
</div>
);
}
}
export default Admin;
in the Auth.js Class change the isAuthanticated to:
isAuthenticated() {
//get token from local storage if there is one
const jwttoken = localStorage.getItem('jwttoken');
const bearer = 'Bearer ' + jwttoken;
const data = new FormData();
// get the website backend main url from .env
const REACT_APP_URL = process.env.REACT_APP_URL
fetch(`${REACT_APP_URL}/api/auth/verify`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': bearer,
},
body: data
}).then(
(response) => {
response.json()
.then((res) => {
if (response.status === 200) {
this.authenticated = true;
}
if (response.status === 401) {
localStorage.removeItem('jwttoken');
this.authenticated = false;
}
})
}
).catch((err) => {
console.log(err)
});
return this.authenticated;
}
in PrivateRoute make sure you call Auth.isAuthanticated()
so you get true or false based on the fetch call witch will set authenticated to true or false and it will return this.authenticated;
you are doing it the right way just check spelling
import React, { Component } from "react";
import { Route, Redirect, } from "react-router-dom";
import Auth from "./Auth"
export const PrivateRoute = ({ component: Component, ...rest }) => {
return (
<Route {...rest} render={(props) => (
Auth.isAuthenticated() === true
? <Component {...props} />
: <Redirect to='/admin' />
)} />
)
}

Is react-router-dom have browser history in reactjs?

Is browserHistory contains in react-router-dom?? If it is not then how I can redirect to a page using history.push?
Here is my code, where to add changes in my code?
LoginForm.js
class LoginForm extends Component {
constructor(props) {
super(props);
this.state = {};
this.onSubmit = this.onSubmit.bind(this);
}
render() {
let {username, password} = this.state;
let {isLoginPending, isLoginSuccess, loginError} = this.props;
return (
<div>
<Back/>
<header>
<h1>Company Login</h1>
</header>
<form name="loginForm" onSubmit={this.onSubmit}>
<div className="imgcontainer">
<img src={avatar} alt={"Avatar"} className={"avatar"}/>
</div>
<div className="form-group-collection">
<div className="form-group">
<label>Username/User ID:</label>
<input name="username" onChange={e => this.setState({username: e.target.value})} value={username}/>
</div>
<div className="form-group">
<label>Password:</label>
<input type="password" name="password" onChange={e => this.setState({password: e.target.value})} value={password}/>
</div>
</div>
<br/>
<input type="submit" value="Login" />
</form>
<footer>Copyright © multihands.com. </footer>
</div>
)
}
onSubmit(e) {
e.preventDefault();
let { username, password } = this.state;
this.props.login(username, password);
this.setState({
username: '',
password: ''
});
}
}
const mapStateToProps = (state) => {
return {
isLoginPending: state.isLoginPending,
isLoginSuccess: state.isLoginSuccess,
loginError: state.loginError
};
}
const mapDispatchToProps = (dispatch) => {
return {
login: (username, password) => dispatch(login(username, password))
};
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
Reducer.js
import logindetls from '../../logindet.json';
const SET_LOGIN_PENDING = 'SET_LOGIN_PENDING';
const SET_LOGIN_SUCCESS = 'SET_LOGIN_SUCCESS';
const SET_LOGIN_ERROR = 'SET_LOGIN_ERROR';
export function login(username, password) {
return dispatch => {
dispatch(setLoginPending(true));
dispatch(setLoginSuccess(false));
dispatch(setLoginError(null));
callLoginApi(username, password, error => {
dispatch(setLoginPending(false));
if (!error) {
dispatch(setLoginSuccess(true));
} else {
dispatch(setLoginError(error));
}
});
}
}
function setLoginPending(isLoginPending) {
return {
type: SET_LOGIN_PENDING,
isLoginPending
};
}
function setLoginSuccess(isLoginSuccess) {
return {
type: SET_LOGIN_SUCCESS,
isLoginSuccess
};
}
function setLoginError(loginError) {
return {
type: SET_LOGIN_ERROR,
loginError
}
}
function callLoginApi(username, password, callback) {
setTimeout(() => {
if (username === logindetls.username && password === logindetls.password)
{
return alert("Successfully Logged in...");
} else {
return alert('Invalid username and password');
}
}, 1000);
}
export default function reducer(state = {
isLoginSuccess: false,
isLoginPending: false,
loginError: null
}, action) {
switch (action.type) {
case SET_LOGIN_PENDING:
return Object.assign({}, state, {
isLoginPending: action.isLoginPending
});
case SET_LOGIN_SUCCESS:
return Object.assign({}, state, {
isLoginSuccess: action.isLoginSuccess
});
case SET_LOGIN_ERROR:
return Object.assign({}, state, {
loginError: action.loginError
});
default:
return state;
}
}
And I add redirecting page(userpage.js) to routes.js page
class Routes extends Component {
render() {
return (
<div>
<Router>
<Switch>
<Route exact path="/" component={HomePage}/>
<Route path="/about" component={About}/>
<Route path="/loginform" component={LoginForm}/>
<Route path="/companies" component={Companies}/>
<Route path="/services" component={Services}/>
<Route path="/contact" component={Contact}/>
<Route path="/userpage" component={UserPage}/>
</Switch>
</Router>
</div>
);
}
}
Where does I need to add my routing code and what is needed to import?? Is there any need to install react-router? Does React-router-dom haven't any property to push??In my code where will I add this routing function??
import { withRouter } from 'react-router-dom'
class LoginForm extends Component {
componentWillReceiveProps(nextProps) {
if (!nextProps.isLoginPending && this.props.isLoginPending) {
if (nextProps.isLoginSuccess) {
this.props.history.push('/path-to-redirect-on-login')
} else {
console.log(this.props.loginError)
}
}
}
render() {
...
}
}
...
LoginForm = withRouter(LoginForm);
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);

Resources