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粉9051445142023-10-31 19:13:17
How to redirect in React Router v6
import { useNavigate } from "react-router-dom"; const navigate = useNavigate(); const handleClick = () => { navigate("/dashboard"); };
P粉3842444732023-10-31 13:19:10
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
react-router-dom. x did it. HOC
v5 from
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("/");