I don't know where I'm going wrong
by clicking the enter button I validate my user and use this.props.history.push ("/ home");
and it doesn't work
my login . js
class LoginForm extends Component {
constructor(props){
super(props);
this.state = {
login:'',
password:'',
};
this.onSubmit = this.onSubmit.bind(this);
this.onChange = this.onChange.bind(this);
}
async onSubmit(e){
e.preventDefault();
const {login, password } = this.state;
const response = await api.post('/login', { login,password });
const user = response.data.user.login;
const {jwt} = response.data;
localStorage.setItem('token', jwt);
localStorage.setItem('user', user);
this.props.history.push("/home");
}
onChange(e){
this.setState({[e.target.name]: e.target.value});
}
render() {
const { errors, login, password, isLoading } = this.state;
return (
<form onSubmit={this.onSubmit}>
<label htmlFor="login">Login</label>
<input type="text" name="login" id="login" value={login} onChange={(e) => this.onChange(e)} placeholder="Informe seu login" />
<label htmlFor="password">Senha</label>
<input type="password" name="password" id="password" value={password} onChange={(e) => this.onChange(e)} placeholder="Informe sua senha"/>
<button className="btnEnt" type="submit">Entrar</button>
</form>
)
}
}
export default LoginForm;
my router . js:
import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import Login from './pages/login/index';
import DashBoard from './pages/dashboard/index';
import PrivateRoute from './auth';
export default function Routes(){
console.log('a')
return(
<BrowserRouter>
<Switch>
<PrivateRoute path="/home" component = {DashBoard}/>
</Switch>
</BrowserRouter>
);
} <PrivateRoute path="/home" component = {DashBoard}/>
</Switch>
</BrowserRouter>
);
}
my auth . js :
import { Route, Redirect} from 'react-router-dom';
const isAuth = () => {
console.log('a');
if(localStorage.getItem('token') !== null) {
return true;
}
return false;
};
const PrivateRoute = ({component: Component, ...rest}) => {
return (
<Route
{...rest}
render={props =>
isAuth() ? (
<Component {...props} />
): (
<Redirect
to={{
pathname: '/',
state: {message: 'Usuário não autorizado'}
}}
/>
)}
/>
);
}
export default PrivateRoute;
my dashboard / index
import React, { Component } from 'react';
import Home from '../../components/Home';
class DashBoard extends Component {
render() {
return (
<Home />
)
}
}
export default DashBoard;
error:
Unhandled Rejection (TypeError): Cannot read property 'push' of
undefined
Uncaught (in promise) TypeError: Cannot read property 'push' of
undefined I really do not know what I can is wrong is not redirecting,
I have tried all possible alternatives.
Before you can use history in your React component, you need to wrap it in withRouter.
https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/withRouter.md
import history from 'add your path'
export default function Routes() {
console.log('a')
return (
<BrowserRouter history={history}>
<Switch>
<PrivateRoute exact path="/home" component={DashBoard} />
</Switch>
</BrowserRouter>
)
}
do changes in router file
import { withRouter } from 'react-router-dom';
export default withRouter(LoginForm);
add withRouter in this component
Related
Im using React 18, React Router 6 and React Auth Kit 2.7
I tried to do login page, as showed in example for RAK link
But i getting this error
Code for Login Component JSX
import React from "react"
import axios from "axios"
import { useIsAuthenticated, useSignIn } from "react-auth-kit"
import { useNavigate, Navigate } from "react-router-dom"
const SignInComponent = () => {
const isAuthenticated = useIsAuthenticated()
const signIn = useSignIn()
const navigate = useNavigate()
const [formData, setFormData] = React.useState({ login: "", password: "" })
async function onSubmit(e) {
e.preventDefault()
axios.post("http://localhost:3030/api/auth/login", formData).then((res) => {
if (res.status === 200) {
if (
signIn({
token: res.data.token,
expiresIn: res.data.expiresIn,
tokenType: "Bearer",
authState: res.data.authUserState,
})
) {
navigate("/profile")
console.log("logged in")
} else {
//Throw error
}
} else {
console.log("da duck you want")
}
})
}
console.log(isAuthenticated())
if (isAuthenticated()) {
// If authenticated user, then redirect to his profile
return <Navigate to={"/profile"} replace />
} else {
return (
<form onSubmit={onSubmit} className="flex flex-col w-96 p-2">
<input
className="text-black mt-2"
type={"login"}
onChange={(e) => setFormData({ ...formData, login: e.target.value })}
/>
<input
className="text-black mt-2"
type={"password"}
onChange={(e) =>
setFormData({ ...formData, password: e.target.value })
}
/>
<button type="submit">Submit</button>
</form>
)
}
}
export default SignInComponent
Routes.jsx
// system
import React from 'react'
import { RequireAuth } from 'react-auth-kit'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
// pages
import DeveloperPage from "../pages/Dev.page";
import MainPage from "../pages/Main.page";
import ProfilePage from "../pages/profile/Profile.page";
import LoginPage from "../pages/Auth/Login.page.auth"
import RegisterPage from "../pages/Auth/Register.page.auth"
// components
// logic
const RoutesComponent = () => {
return (
<BrowserRouter>
<Routes>
{/* main */}
<Route path={"/"} element={<MainPage />} />
{/* Authentication */}
<Route path={"/login"} element={<LoginPage />} />
<Route path={"/register"} element={<RegisterPage />} />
{/* Developer */}
<Route path={"/dev"} element={<DeveloperPage />} />
{/* Other */}
<Route path={"/profile"} element={
<RequireAuth loginPath={"/login"}>
<ProfilePage />
</RequireAuth>
} />
</Routes>
</BrowserRouter>
);
};
export default RoutesComponent;
Profile.jsx
import React, { useState } from 'react'
export default function App() {
return (
<div className="wrapper">
<h1>Profile</h1>
</div>
);
}
Im already tried searching this error all over stackoverflow, github issues and link that provided by error but still dont understand how to fix error in my example
Updated:
App.jsx
import React from "react";
import { AuthProvider } from "react-auth-kit";
import RoutesComponent from "./routes/router";
import "./index.css";
function App() {
return (
<AuthProvider authName={"_auth"} authType={"localstorage"}>
<RoutesComponent />
</AuthProvider>
);
}
export default App;
Have you put your application inside AuthProvider? https://github.com/react-auth-kit/react-auth-kit/blob/master/examples/create-react-app/src/App.js
I'm currently in the process of learning React JS.Tutorial D.O
I already have a PHP backend before and I want to create a login form where the result of the backend is JWT.
I use a custom hook in React JS for that.
Here is the code that I created.
App.js
import "./App.css";
import React from "react";
import { Routes } from "../config";
import { useToken } from "../hooks";
import Login from "./Login";
const App = () => {
const { token, setToken } = useToken();
if (!token) {
return <Login setToken={setToken} />;
}
return <Routes />;
};
export default App;
useToken()
import { useState } from "react";
export default function useToken() {
const getToken = () => {
const tokenString = localStorage.getItem("token");
const userToken = JSON.parse(tokenString);
return userToken?.token;
};
const [token, setToken] = useState(getToken());
const saveToken = (userToken) => {
localStorage.setItem("token", JSON.stringify(userToken));
setToken(userToken.token);
};
return {
setToken: saveToken,
token,
};
}
Login/index.js
import React, { useState } from "react";
import PropTypes from "prop-types";
import { Button, Card, Col, Container, Form, Row } from "react-bootstrap";
import "./login.css";
async function loginUser(credentials) {
const url = "v1/auth";
const user = new FormData();
user.append("username", credentials.username);
user.append("password", credentials.password);
return fetch(url, {
method: "POST",
body: user,
}).then((data) => data.json());
}
export default function Login({ setToken }) {
const [username, setUserName] = useState();
const [password, setPassword] = useState();
// Handle submit
const handleSubmit = async (e) => {
e.preventDefault();
const token = await loginUser({ username, password });
setToken(token);
};
return (
<div id="login-page">
<Container>
<Row className="d-flex justify-content-md-center align-items-center vh-100">
<Col sm={12} md={6}>
<Card>
<Form onSubmit={handleSubmit}>
<Card.Header>Sign In</Card.Header>
<Card.Body>
<Form.Group controlId="loginform-username">
<Form.Label>Username</Form.Label>
<Form.Control
type="text"
placeholder="Username"
name="username"
onChange={(e) => setUserName(e.target.value)}
/>
</Form.Group>
<Form.Group controlId="loginform-password">
<Form.Label>Password</Form.Label>
<Form.Control
name="password"
type="password"
placeholder="Password"
onChange={(e) => setPassword(e.target.value)}
/>
</Form.Group>
</Card.Body>
<Card.Footer>
<Button
variant="primary"
type="submit"
className="float-right"
>
Login
</Button>
<div className="clearfix"></div>
</Card.Footer>
</Form>
</Card>
</Col>
</Row>
</Container>
</div>
);
}
Login.propTypes = {
setToken: PropTypes.func.isRequired,
};
When I login successfully, I save the token to local storage. But I got the following warning.
index.js:1 Warning: Failed prop type: The prop `setToken` is marked as required in `Login`, but its value is `undefined`.
How to solve this?. Any help it so appreciated
Updated
Routes
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { Login, Home } from "../../pages";
const Routes = () => {
return (
<Router>
<Switch>
<Route path="/login">
<Login />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
);
};
export default Routes;
In Routes you call Login but never pass it setToken, which is required. One option is to pass the setToken function down through Routes:
App.js
import "./App.css";
import React from "react";
import { Routes } from "../config";
import { useToken } from "../hooks";
import Login from "./Login";
const App = () => {
const { token, setToken } = useToken();
if (!token) {
return <Login setToken={setToken} />;
}
return <Routes setToken={setToken} />;
};
export default App;
Routes.js
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { Login, Home } from "../../pages";
const Routes = ({ setToken }) => {
return (
<Router>
<Switch>
<Route path="/login">
<Login setToken={setToken} />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
);
};
export default Routes;
<Route path="/login">
<Login /> /* <--- this line is calling Login component but is passing setToken as undefined */
</Route>
I have
<Route path='/login' exact render={() => <LoginPage sectionEmailHandler={this.sectionEmailHandler} />} />
this Route with path /login ,and i am passing callback function
sectionEmailHandler
and inside login component i am doing
this.props.history.push('/dashboard/session')
so now i am ,getting the error that
TypeError: Cannot read property 'push' of undefined
but when i did not pass the callback function with /login route like this
<Route path='/login' exact component={LoginPage} />
then it works fine.
Below is my code
Pages/index.js
import React, { Component } from 'react'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import LoginPage from '../components/Login/LoginPage'
import StartPage from '../components/startPage/StartHere'
import users from '../pages/users/index'
class Home extends Component {
// constructor(props){
// super(props)
// this.state={
// email:''
// }
// }
sectionEmailHandler=(email)=>{
console.log(email)
}
render() {
return (
<>
<Router >
<Switch>
<Route path='/' exact component={StartPage} />
<Route path='/login' exact render={() => <LoginPage sectionEmailHandler={this.sectionEmailHandler} />} />
<Route path='/dashboard/session' exact component={users} />
</Switch>
</Router>
</>
)
}
}
export default Home;
LoginPage.js
import React, { Component } from 'react'
import { Redirect } from 'react-router-dom';
import { Button,Label } from 'reactstrap';
import {Mutation, Query} from 'react-apollo';
import gql from 'graphql-tag'
import LoginPage_logo_img from '../../Assets/LoginPage_logo_img.png'
import LoginPage_email_icon from '../../Assets/LoginPage_email_icon.svg'
import LoginPage_lock_icon from '../../Assets/LoginPage_lock_icon.svg'
import './LoginPage.css'
const AUTH_USER = gql`
mutation TokenAuth($username: String!,$password : String!) {
tokenAuth(username: $username,password : $password) {
token,
payload,
refreshExpiresIn
}
}
`;
class LoginPage extends Component {
constructor(props){
super(props)
this.state={
fields: {},
errors: {},
email:'',
password:''
}
this.textInputemail = React.createRef();
this.textInputpassword = React.createRef();
}
handleValidation(){
let fields = this.state.fields;
let errors = {};
let formIsValid = true;
//Email
if(!fields["email"]){
formIsValid = false;
errors["email"] = "Please complete the field above";
}
if(typeof fields["email"] !== "undefined"){
let lastAtPos = fields["email"].lastIndexOf('#');
let lastDotPos = fields["email"].lastIndexOf('.');
if (!(lastAtPos < lastDotPos && lastAtPos > 0 && fields["email"].indexOf('##') == -1 && lastDotPos > 2 && (fields["email"].length - lastDotPos) > 2)) {
formIsValid = false;
errors["email"] = "Please enter the valid Email";
}
}
this.setState({errors: errors});
return formIsValid;
}
handleChnage=()=>{
let fields = this.state.fields;
fields[this.textInputpassword.current.name] = this.textInputpassword.current.value;
fields[this.textInputemail.current.name] = this.textInputemail.current.value;
this.setState({fields});
}
render() {
return (
<Mutation mutation={AUTH_USER}>
{(authUser,{data})=>(
<div className="LoginPage-container">
<div className="LoginPage-wrapper">
<img src={LoginPage_logo_img} alt="" className="LoginPage-logo"/>
<div className="LoginPage-email">
<img src={LoginPage_email_icon} alt=""/>
<input ref={this.textInputemail} type="email" name="email" onChange={this.handleChnage}/>
</div>
<div className="LoginPage-password">
<img src={LoginPage_lock_icon} alt=""/>
<input ref={this.textInputpassword} type="password" name="password" placeholder="Password" onChange={this.handleChnage}/>
</div>
<Button className="LoginPage-signIn" onClick={(e)=>{
e.preventDefault()
const {email,password}= this.state.fields;
authUser({
variables:{
username:email,
password:password
}
}).then((res)=>{
let token=res.data.tokenAuth.token;
localStorage.setItem('WonEToken', token);
this.props.sectionEmailHandler(email)
console.log(this.props)
this.props.router.push('/dashboard/session');
}).catch((err)=>{
console.log(err+'Error while fetching the user details');
})
}}>Sign In</Button>
<h2></h2>
</div>
</div>
)}
</Mutation>
)
}
}
export default LoginPage
Pass the route props from the Route on to the rendered component.
<Route
path='/login'
exact
render={(routeProps) => ( // <-- { history, location, match }
<LoginPage
sectionEmailHandler={this.sectionEmailHandler}
{...routeProps} // <-- spread in to component
/>
)}
/>
I assume you are using react router.
In your example
<Route path='/login' exact render={() => <LoginPage sectionEmailHandler={this.sectionEmailHandler} />} />
You need to pass in the props like this.
<Route path='/login' exact render={(props) => <LoginPage sectionEmailHandler={this.sectionEmailHandler} {...props} />} />
The props contains match, location, history
The children render prop receives all the same route props as the
component and render methods, except when a route fails to match the
URL, then match is null.
i m building react login app with react protected route jwt authnetication my login component working fine but when i go to dashboard and i update the url manually its redirect me login page without logout.
const PrivateRoute = ({ component: Component, ...rest }) => {
//const auth = useSelector(state => state.auth)
let auth = localStorage.getItem('token')
const [isAuthenticated, setIsAuthenticated] = useState(null)
useEffect(() => {
let token = localStorage.getItem('token')
if(token){
let tokenExpiration = jwtDecode(token).exp;
let dateNow = new Date();
console.log(tokenExpiration)
if(tokenExpiration < dateNow.getTime()/1000){
setIsAuthenticated(false)
}else{
setIsAuthenticated(true)
}
} else {
setIsAuthenticated(false)
}
// eslint-disable-next-line }, [auth])
if(isAuthenticated === null){
return <></> }
return (
<Route {...rest} render={props =>
!isAuthenticated ? (
<Redirect to='/login'/>
) : (
)
}
/> ); };
Please try the below code. You can use the private route separate file
PrivateRoute.js
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
export const PrivateRoute = ({ component: Component, ...rest }) => {
return (
<React.Fragment>
<Route {...rest} render={props => (
localStorage.getItem('token')
? <Component {...props} />
: <Redirect to={{ pathname: '/login'}} />
)} />
</React.Fragment>
)
}
Route.js
import React, { Component } from 'react';
import {Route, Switch} from 'react-router-dom';
import Login from './components/Login/Login'
import { PrivateRoute } from "./PrivateRoute";
import Dashboard from "./components/Home/Dashboard";
import Notfound from './Notfound';
class Routes extends Component {
render() {
return (
<React.Fragment>
<Switch>
<PrivateRoute exact path="/" component={Dashboard} label="Home"/>
<Route path="/login" component={Login} />
<Route path="*" component={Notfound} />
</Switch>
</React.Fragment>
)
}
}
export default Routes;
I am trying to get the pages by using URL but components are not rendered in the browser even I am not getting the error. So it's very hard to resolve the error.
Please Help me to get the issue.
import React, { Component } from 'react';
import { BrowserRouter as Router} from 'react-router-dom';
import Route from 'react-router-dom/Route';
class ToDoApp extends Component {
render() {
return (
<Router>
<div className="ToDoApp">
<Route path="/" exact strict Component={Index} />
<Route path="/welcome" exact strict Component={WelcomePage} />
<Route path="/login" exact strict Component={Login} />
</div>
</Router>
);
}
}
class Index extends Component {
render() {
return (<div><h1>Welcome</h1></div>);
}
}
class WelcomePage extends Component {
render() {
return (
<div>
Welcome Page
</div>
);
}
}
class Login extends Component {
constructor(props) {
super(props);
this.state = {
username: 'Ganesh',
password: '',
hasLoginFailed: false,
showSucessMessage: false
}
this.handleChange = this.handleChange.bind(this);
this.loginCheck = this.loginCheck.bind(this);
}
handleChange(event) {
this.setState({
[event.target.name]: event.target.value // for declaring variable we use []
})
}
loginCheck() {
if (this.state.username === "Ganesh" && this.state.password === 'admin') {
console.log('successful');
this.setState({ showSucessMessage: true, hasLoginFailed: false })
} else {
console.log('failed');
this.setState({ hasLoginFailed: true, showSucessMessage: false })
}
}
render() {
return (
<div>
{/* True && 'String Value' -> String Value
False && 'String Value' -> false */}
{this.state.hasLoginFailed && <div>Invalid Login</div>}
{this.state.showSucessMessage && <div>Valid Login</div>}
UserName : <input type="text" name="username" value={this.state.username} onChange={this.handleChange} />
Password : <input type="password" name="password" value={this.state.password} onChange={this.handleChange} />
<button onClick={this.loginCheck}>Login</button>
</div>
)
}
}
export default ToDoApp
if I put localhost:3000/login -> Login Component should be displayed
if I put localhost:3000/welcome -> WelcomePage Component should be displayed
But now I am getting the blank page
import React from 'react';
import { BrowserRouter as Router, Routes, Route, } from "react-
router-dom";
import './App.css';
import Home from './components/Pages/Home';
function App() {
return (
<>
<Router>
<Routes>
<Route exact path='/' element={<Home/>}/>
</Routes>
</Router>
</>
)}
export default App;