i've been trying since days to redirect my user after login to the home creating a callback function in my App.js and sending it as props to the login class component throught a loginregisterpage class component, but this doesn't work, can someone have a look on it and tell me what i;m missing out? Thank you my code look like this
App.js
import React from 'react'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
import { HomePage } from './Pages/HomePage/HomePage'
import { LoginRegisterPage } from './Pages/LoginRegisterPage/LoginRegisterPage'
import 'bootstrap/dist/css/bootstrap.min.css'
export class App extends React.Component {
constructor(props) {
super(props);
this.state = {
authenticated: false,
}
this.handleSuccess = this.handleSuccess.bind(this);
}
handleSuccess = (data) => {
this.props.history.push("/")
}
render() {
return (
<Router>
<Switch>
<Route exact path="/">
<HomePage />
</Route>
<Route exact path="/login-register">
<LoginRegisterPage onLoginSuccess={this.handleSuccess} />
</Switch>
</Router>
)
}
}
LoginRegisterPage class component
class LoginPage extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: '',
accessToken: '',
authenticated: ''
};
this.handleChangeUsername = this.handleChangeUsername.bind(this);
this.handleChangePassword = this.handleChangePassword.bind(this);
}
handleChangeUsername(event) {
this.setState({
username: event.target.value
})
}
handleChangePassword(event) {
this.setState({
password: event.target.value
})
}
handleClick(event) {
var apiBaseUrl = "https://myapi.com/auth/"
const payload = {
method: "POST",
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
body: JSON.stringify({
'username': this.state.username,
'password': this.state.password
})
};
const { username, password } = this.state;
if (username && password) {
fetch(apiBaseUrl + 'login', payload)
.then((response) => {
if (response.status === 200) {
alert("Logged In! You'll be redirected on Home")
return response.json()
} else {
return alert("wrong pass")
}
}).then((data) => {
this.setState({
accessToken: data.accestToken,
authenticated: data.authenticated
});
localStorage.setItem('accessToken', data.accessToken);
if (data.authenticated === true) {
console.log(this.props)
this.props.onLoginSuccess(data)
}
})
.catch((err) => console.log(err));
} else {
alert("Cannot be Empty")
}
}
render() {
return (
<div>
<div className="form">
<div>
<div className="form-input">
<div >
<div className="userData">
<span>
<img
src={UserIcon}
/>
</span>
<input
autocomplete="off"
type="text"
name="username"
placeholder="Username"
value={this.state.username}
onChange={this.handleChangeUsername}
/>
</div>
<div className="userData">
<span>
<img
src={PasswordIcon}
/>
</span>
<input
autocomplete="off"
type="password"
name="password"
placeholder="Password"
value={this.state.password}
onChange={this.handleChangePassword}
/>
<p style={(this.state.username && this.state.password) ? { display: 'none' } : { display: 'block' }}> Must fill all the form!</p>
</div>
</div>
</div>
</div>
</div>
<div className="form-footer">
<img
src={Btn}
onClick={(event) => this.handleClick(event)}
/>
</div>
</div>
);
}
}
LoginPage class component
class LoginPage extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: '',
accessToken: '',
authenticated: ''
};
this.handleChangeUsername = this.handleChangeUsername.bind(this);
this.handleChangePassword = this.handleChangePassword.bind(this);
}
handleChangeUsername(event) {
this.setState({
username: event.target.value
})
}
handleChangePassword(event) {
this.setState({
password: event.target.value
})
}
handleClick(event) {
var apiBaseUrl = "https://movies-app-siit.herokuapp.com/auth/"
const payload = {
method: "POST",
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
body: JSON.stringify({
'username': this.state.username,
'password': this.state.password
})
};
const { username, password } = this.state;
if (username && password) {
fetch(apiBaseUrl + 'login', payload)
.then((response) => {
if (response.status === 200) {
alert("Logged In! You'll be redirected on Home")
return response.json()
} else {
return alert("wrong pass")
}
}).then((data) => {
this.setState({
accessToken: data.accestToken,
authenticated: data.authenticated
});
localStorage.setItem('accessToken', data.accessToken);
if (data.authenticated === true) {
console.log(this.props)
this.props.onLoginSuccess(data)
}
})
.catch((err) => console.log(err));
} else {
alert("Cannot be Empty")
}
}
render() {
return (
<div>
<div className="form">
<div>
<div className="form-input">
<div >
<div className="userData">
<span>
<img
src={UserIcon}
/>
</span>
<input
autocomplete="off"
type="text"
name="username"
placeholder="Username"
value={this.state.username}
onChange={this.handleChangeUsername}
/>
</div>
<div className="userData">
<span>
<img
src={PasswordIcon}
/>
</span>
<input
autocomplete="off"
type="password"
name="password"
placeholder="Password"
value={this.state.password}
onChange={this.handleChangePassword}
/>
<p style={(this.state.username && this.state.password) ? { display: 'none' } : { display: 'block' }}> Must fill all the form!</p>
</div>
</div>
</div>
</div>
</div>
<div className="form-footer">
<img
src={Btn}
onClick={(event) => this.handleClick(event)}
/>
</div>
</div>
);
}
}
The most common ways to implement redirection logic after login are: using HTTP Referer header. saving the original request in the session. appending original URL to the redirected login URL.
The Redirect component was usually used in previous versions of the react-router-dom package to quickly do redirects by simply importing the component from react-router-dom and then making use of the component by providing the to prop, passing the page you desire to redirect to.
To redirect to another page on button click in React: Use the useNavigate() hook, e.g. const navigate = useNavigate(); . Call the navigate() function, passing it the path - navigate('/about') . The navigate() function lets us navigate programmatically.
If you're using React Router you can use the Redirect component:
import { Redirect } from 'react-router-dom';
export default function PrivateRoute () {
if (notLoggedIn()) {
return <Redirect to="/login"/>;
}
// return your component
}
But if you're not inside a render function (i.e. you're in a submit callback) or you want to rewrite browser history, use the useHistory hook (note: hooks work only in function components, not class components)
import { useHistory } from 'react-router-dom';
const history = useHistory();
// After your login action you can redirect with this command:
history.push('/otherRoute');
App is defined outside the Router component so it has no history prop function to call to do any navigation.
Have the LoginRegisterPage component navigate upon successful authentication. It will need to access the history object of the nearest Router context. Normally this is achieved by consuming passed route props from the Route component.
You can:
Move LoginRegisterPage to be rendered by the component prop of the Route so it receives the route props and thus the history object as a prop.
<Route exact path="/login-register" component={LoginRegisterPage} />
LoginRegisterPage
class LoginPage extends React.Component {
constructor(props) {
...
}
...
handleClick(event) {
var apiBaseUrl = "https://myapi.com/auth/"
const payload = {...};
const { username, password } = this.state;
const { history } = this.props; // <-- destructure history from props
if (username && password) {
fetch(apiBaseUrl + 'login', payload)
.then((response) => {
...
}).then((data) => {
this.setState({
accessToken: data.accestToken,
authenticated: data.authenticated
});
localStorage.setItem('accessToken', data.accessToken);
if (data.authenticated === true) {
console.log(this.props)
this.props.history.push("/"); // <-- navigate!
}
})
.catch((err) => console.log(err));
} else {
alert("Cannot be Empty")
}
}
render() {
...
}
}
Decorate your LoginRegisterPage with the withRouter Higher Order Component so the route props are injected as props.
import { withRouter } from 'react-router-dom;
...
const LoginPageWithRouter = withRouter(LoginPage);
If you prefer to do a redirect then replace any history.push calls with history.replace. push is a normal navigation and pushes on a new path on the history state whereas replace replaces the current history entry in the stack. After the auth redirect you probably don't want users to back navigate back to your login page/route.
If you need the handleSuccess callback to manage some auth state in App then I think it best to let App manage the authentication state and the LoginPage to still handle navigation. In this case, go with the second solution above so it receives both the handleSuccess callback and the history object.
if (data.authenticated === true) {
this.props.onLoginSuccess(data); // <-- callback to parent to set state
this.props.history.replace("/"); // <-- imperative navigation
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With