以编程方式重定向到 React Router v6 中的路由时出现问题
Problem in redirecting programmatically to a route in react router v6
我想对某些用户操作执行导航,比如按钮的提交。假设用户单击“添加联系人”按钮,我希望 react-router 重定向到主页“/”。目前我正面临这个问题 --> 类型错误:无法读取未定义的属性(读取 'push')。作为初学者,非常感谢专家的帮助。
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;
这是 App.js 文件
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;
问题
TypeError: Cannot read properties of undefined (reading 'push')
这是因为您试图从 navigate
不存在的 prop 导航,它是未定义的。
this.props.navigate.push("/");
useNavigate
挂钩仅与函数组件兼容,因此 want/need 要将 navigate
与 class 组件一起使用,您必须转换 AddContacts
到函数组件,或者滚动你自己的自定义 withRouter
高阶组件来注入“路由道具”,就像 react-router-dom
v5.x 中的 withRouter
HOC 所做的那样。
解决方案
我不会介绍如何将 class 组件转换为函数组件。这是一个示例自定义 withRouter
HOC:
const withRouter = WrappedComponent => props => {
const navigate = useNavigate();
// etc... other react-router-dom v6 hooks
return (
<WrappedComponent
{...props}
navigate={navigate}
// etc...
/>
);
};
并用新的 HOC 装饰 AddContacts
组件。
export default withRouter(AddContacts);
现在,这会将 navigate
道具( 和您设置的任何其他道具 )传递给装饰组件,现在将定义 this.navigate
。
此外,导航 API 从 v5 更改为 v6,它不再是直接使用的 history
对象。 navigate
是一个函数而不是一个对象。要使用调用函数并传递 1 或 2 个参数,第一个是目标路径,第二个是可选的“选项”对象 replace
and/or state
key/values .
interface NavigateFunction {
(
to: To,
options?: { replace?: boolean; state?: State }
): void;
(delta: number): void;
}
现在导航如下:
this.props.navigate("/");
我想对某些用户操作执行导航,比如按钮的提交。假设用户单击“添加联系人”按钮,我希望 react-router 重定向到主页“/”。目前我正面临这个问题 --> 类型错误:无法读取未定义的属性(读取 'push')。作为初学者,非常感谢专家的帮助。
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;
这是 App.js 文件
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;
问题
TypeError: Cannot read properties of undefined (reading 'push')
这是因为您试图从 navigate
不存在的 prop 导航,它是未定义的。
this.props.navigate.push("/");
useNavigate
挂钩仅与函数组件兼容,因此 want/need 要将 navigate
与 class 组件一起使用,您必须转换 AddContacts
到函数组件,或者滚动你自己的自定义 withRouter
高阶组件来注入“路由道具”,就像 react-router-dom
v5.x 中的 withRouter
HOC 所做的那样。
解决方案
我不会介绍如何将 class 组件转换为函数组件。这是一个示例自定义 withRouter
HOC:
const withRouter = WrappedComponent => props => {
const navigate = useNavigate();
// etc... other react-router-dom v6 hooks
return (
<WrappedComponent
{...props}
navigate={navigate}
// etc...
/>
);
};
并用新的 HOC 装饰 AddContacts
组件。
export default withRouter(AddContacts);
现在,这会将 navigate
道具( 和您设置的任何其他道具 )传递给装饰组件,现在将定义 this.navigate
。
此外,导航 API 从 v5 更改为 v6,它不再是直接使用的 history
对象。 navigate
是一个函数而不是一个对象。要使用调用函数并传递 1 或 2 个参数,第一个是目标路径,第二个是可选的“选项”对象 replace
and/or state
key/values .
interface NavigateFunction { ( to: To, options?: { replace?: boolean; state?: State } ): void; (delta: number): void; }
现在导航如下:
this.props.navigate("/");