I have a simple form which sends the request to my API and either displays the error under form, or redirects to another page. Or, at least, it's supposed to. This is my form:
import React from "react";
import { Button, Form } from "react-bootstrap";
import '../Auth.css';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
import { Redirect } from 'react-router'
function SendRegisterRequest(email, username, password){
let navigate = useNavigate();
var body = {
email: email,
username: username,
password: password
};
axios.post('https://localhost:5001/api/v1/identity/register', body)
.then(function (response) {
navigate("/confirm");
})
.catch(function (error) {
document.getElementById("errorMessage").innerHTML = error.response.data.errors[0];
});
}
class Register extends React.Component {
constructor(props) {
super(props);
this.state = {
email: '',
username: '',
password: '',
cpassword: '',
};
this.handleEmailChange = this.handleEmailChange.bind(this);
this.handlePasswordChange = this.handlePasswordChange.bind(this);
this.handleUsernameChange = this.handleUsernameChange.bind(this);
this.handleCpasswordChange = this.handleCpasswordChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleEmailChange = (event) => {
this.setState({ email: event.target.value });
}
handleUsernameChange = (event) => {
this.setState({ username: event.target.value });
}
handlePasswordChange = (event) => {
this.setState({ password: event.target.value });
}
handleCpasswordChange = (event) => {
this.setState({ cpassword: event.target.value });
}
handleSubmit = (event) => {
event.preventDefault();
if (this.state.password != this.state.cpassword){
document.getElementById("errorMessage").innerHTML = "Passwords don't match!";
}
else {
SendRegisterRequest(this.state.email, this.state.username, this.state.password);
}
}
render() {
return (
<div className="Login">
<Form onSubmit={this.handleSubmit}>
<Form.Group size="lg" controlId="email">
<Form.Label>Email</Form.Label>
<Form.Control
type="email"
value={this.state.email}
onChange={this.handleEmailChange}
/>
</Form.Group>
<Form.Group size="lg" controlId="email">
<Form.Label>Username</Form.Label>
<Form.Control
type="text"
value={this.state.username}
onChange={this.handleUsernameChange}
/>
</Form.Group>
<Form.Group size="lg" controlId="email">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
value={this.state.password}
onChange={this.handlePasswordChange}
/>
</Form.Group>
<Form.Group size="lg" controlId="password">
<Form.Label>Confirm password</Form.Label>
<Form.Control
type="password"
value={this.state.cpassword}
onChange={this.handleCpasswordChange}
/>
</Form.Group>
<p id="errorMessage"></p>
<Button size="lg" type="submit" >
Login
</Button>
</Form>
</div>
);
}
}
export default Register
The SendRegisterRequest()
is called on submitting the form. Using navigate
was causing errors because I can't use hooks in functions. I have also tried returning the <Navigate/>
component:
axios.post('https://localhost:5001/api/v1/identity/register', body)
.then(function (response) {
return <Navigate to="/confirm"/>
})
.catch(function (error) {
document.getElementById("errorMessage").innerHTML = error.response.data.errors[0];
});
And after debugging, I can see that return <Navigate to="/confirm"/>
is being hit, but nothings happens. What am I doing wrong here? Or maybe is there any other way that I can simply redirect to another page?
CodePudding user response:
You can use history
which, per react-router docs:
refers to the history package, which is one of only 2 major dependencies of React Router (besides React itself)
Step by step below:
- Create a
history
instance:
import { createBrowserHistory } from 'history';
export const history = createBrowserHistory();
- Pass created
history
instance to main app router
import { Router } from 'react-router-dom';
// in an app main render() if class component or return if functional component:
<Router history={history}>
<RestOfApp/>
</Router>
- Import the same
history
instance in youraxios
method and call
history.push('/confirm')
More info how to use the history
package can be found in it's docs (v5)
CodePudding user response:
I found the solution, but it is a bit inelegant and won't satisify those who want their page to work without refreshing.
Inspired by @kmnowak I experimented a bit and finally did this:
import { createBrowserHistory } from "history";
function SendRegisterRequest(email, username, password) {
const history = createBrowserHistory({forceRefresh:true});
var body = {
email: email,
username: username,
password: password
};
axios.post('https://localhost:5001/api/v1/identity/register', body)
.then(function (response) {
history.push('/posts');
document.location.reload()
})
.catch(function (error) {
document.getElementById("errorMessage").innerHTML = error.response.data.errors[0];
});
}
the history.push('/posts')
changes the URL route, but doesn't change the page content, so I use document.location.reload()
to force reload the page.
CodePudding user response:
Convert your Register Class Component into Functional Component . Create navigate in Register class component and pass navigate in SendRegisterRequest method.
function SendRegisterRequest(email, username, password,navigate){
var body = {
email: email,
username: username,
password: password
};
axios.post('https://localhost:5001/api/v1/identity/register', body)
.then(function (response) {
navigate("/confirm");
})
.catch(function (error) {
document.getElementById("errorMessage").innerHTML = error.response.data.errors[0];
});
}
function Register (){
const navigate=useNavigate();
...
handleSubmit = (event) => {
...
SendRegisterRequest(email, username, password,navigate);
}
}
}