Issues when programmatically redirecting to routes in React Router v6
P粉693126115
P粉693126115 2023-10-30 19:35:07
0
2
637

I want to perform navigation on some user actions, such as onSubmit of a button. Assuming the user clicks the "Add Contact" button, I want react-router to redirect in the homepage "/". Currently I'm facing this issue --> TypeError: Cannot readproperties of undefined (reading 'push'). As a beginner, I would really appreciate the help from experts.

AddContacts.js

import React, { Component } from "react";
import { Consumer } from "../../context";
import TextInputGroup from "../layout/TextInputGroup";
import { v4 as uuidv4 } from "uuid";
import { useNavigate } from "react-router-dom";

class AddContacts extends Component {
  state = {
    name: "",
    email: "",
    phone: "",
    errors: {},
  };
  onSubmit = (dispatch, e) => {
    e.preventDefault();

    const { name, email, phone } = this.state;

    //Check for errors

    if (name === "") {
      this.setState({ errors: { name: "Name is required" } });
      return;
    }
    if (email === "") {
      this.setState({ errors: { email: "Email is required" } });
      return;
    }
    if (phone === "") {
      this.setState({ errors: { phone: "Phone is required" } });
      return;
    }

    const newContact = {
      id: uuidv4(),
      name,
      email,
      phone,
    };
    dispatch({ type: "ADD_CONTACT", payload: newContact });

    this.setState({
      name: "",
      email: "",
      phone: "",
      errors: {},
    });
    this.props.navigate.push("/");
  };

  onChange = (e) => this.setState({ [e.target.name]: e.target.value });
  render() {
    const { name, email, phone, errors } = this.state;

    return (
      <Consumer>
        {(value) => {
          const { dispatch } = value;

          return (
            <div className="card mb-3">
              <div className="card-header">Add Contacts</div>
              <div className="card-body">
                <form onSubmit={this.onSubmit.bind(this, dispatch)}>
                  <TextInputGroup
                    label="Name"
                    name="name"
                    placeholder="Enter Name..."
                    value={name}
                    onChange={this.onChange}
                    error={errors.name}
                  />
                  <TextInputGroup
                    label="Email"
                    name="email"
                    type="email"
                    placeholder="Enter Email..."
                    value={email}
                    onChange={this.onChange}
                    error={errors.email}
                  />
                  <TextInputGroup
                    label="Phone"
                    name="phone"
                    placeholder="Enter Phone..."
                    value={phone}
                    onChange={this.onChange}
                    error={errors.phone}
                  />
                  <input
                    type="submit"
                    value="Add Contact"
                    className="btn btn-light btn-block mt-3"
                  />
                </form>
              </div>
            </div>
          );
        }}
      </Consumer>
    );
  }
}

export default AddContacts;

This is the App.js file

import React, { Component } from "react";
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

import Contacts from "./components/contacts/Contacts";
import Header from "./components/layout/Header";
import AddContacts from "./components/contacts/AddContacts";
import About from "./components/pages/About";

import { Provider } from "./context";

import "bootstrap/dist/css/bootstrap.min.css";
import "./App.css";

function App() {
  return (
    <Provider>
      <BrowserRouter>
        <div className="App">
          <Header branding="Contact manager" />
          <div className="container">
            <Routes>
              <Route path="/" element={<Contacts />} />{" "}
              <Route path="/contact/add/*" element={<AddContacts />} />{" "}
              <Route path="about/*" element={<About />} />{" "}
            </Routes>{" "}
          </div>{" "}
        </div>{" "}
      </BrowserRouter>{" "}
    </Provider>
  );
}

export default App;


P粉693126115
P粉693126115

reply all(2)
P粉905144514

How to redirect in React Router v6

import {  useNavigate  } from "react-router-dom";

  const navigate = useNavigate();
  
  const handleClick = () => {
    navigate("/dashboard");
  };
P粉384244473

question

This is because you are trying to navigate from a navigate property that does not exist, it is undefined.

this.props.navigate.push("/");
The

useNavigate hook is only compatible with function components, so if you want/need to use navigate with a class component, you must convert AddContacts code> to a function component, or roll your own custom withRouter higher-order component to inject "route props", such as the withRouter HOC v5 from react-router-dom. x did it.

solution

I will not introduce how to convert class components into function components. Here is an example of a custom withRouter HOC:

const withRouter = WrappedComponent => props => {
  const navigate = useNavigate();
  // etc... other react-router-dom v6 hooks

  return (
    <WrappedComponent
      {...props}
      navigate={navigate}
      // etc...
    />
  );
};

And decorate the AddContacts component with the new HOC.

export default withRouter(AddContacts);

The navigate property (and any other properties you set) will now be passed to the decorated component, and this.navigate will now be defined.

Additionally, the navigation API changed from v5 to v6 and no longer uses direct history objects. navigate is a function not an object. To use you call the function and pass 1 or 2 arguments, the first is the target path and the second is an optional "option" with the replace and/or state keys Object/Value.

Now the navigation is as follows:

this.props.navigate("/");
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template