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;
How to redirect in React Router v6
question
This is because you are trying to navigate from a
Thenavigate
property that does not exist, it is undefined.useNavigate
hook is only compatible with function components, so if you want/need to usenavigate
with a class component, you must convertAddContacts code> to a function component, or roll your own custom
withRouter
higher-order component to inject "route props", such as thewithRouter
react-router-dom. x did it.HOC
v5 fromsolution
I will not introduce how to convert class components into function components. Here is an example of a custom
withRouter
HOC:And decorate the
AddContacts
component with the new HOC.The
navigate
property (and any other properties you set) will now be passed to the decorated component, andthis.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 thereplace
and/orstate
keys Object/Value.Now the navigation is as follows: