Home > Back-end >  How can I redirect from a class component?
How can I redirect from a class component?

Time:03-31

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:

  1. Create a history instance:
import { createBrowserHistory } from 'history';

export const history = createBrowserHistory();
  1. 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>
  1. Import the same history instance in your axios 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);
        }
    }
}
  • Related