以编程方式重定向到反应路由器 v6 中的路由的问题
Posted
技术标签:
【中文标题】以编程方式重定向到反应路由器 v6 中的路由的问题【英文标题】:Problem in redirecting programmatically to a route in react router v6 【发布时间】:2022-01-19 14:04:57 【问题描述】:我想对某些用户操作执行导航,比如按钮的 onSubmit。假设用户单击添加联系人按钮,我希望 react-router 在主页“/”中重定向。目前我正面临这个问题——> TypeError: Cannot read properties of undefined (reading '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;
【问题讨论】:
你看过文档中的这个例子了吗?它通过useNavigation
钩子涵盖了这个确切的用例。 reactrouter.com/docs/en/v6/examples/auth
【参考方案1】:
问题
TypeError: Cannot read properties of undefined (reading 'push')
这是因为您尝试从不存在的 navigate
属性导航,它是未定义的。
this.props.navigate.push("/");
useNavigate
钩子仅与函数组件兼容,因此您想要/需要将navigate
与类组件一起使用,您必须将AddContacts
转换为函数组件,或者滚动您自己的自定义withRouter
高阶组件注入“路由道具”,如来自react-router-dom
v5.x 的withRouter
HOC。
解决方案
我不会介绍将类组件转换为函数组件。这是一个示例自定义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
和/或 state
键/值的可选“选项”对象。
interface NavigateFunction ( to: To, options?: replace?: boolean; state?: State ): void; (delta: number): void;
现在如下导航:
this.props.navigate("/");
【讨论】:
对于基于类的组件,除了转换为功能组件外,还有其他方法可以通过编程方式导航吗? 应该有办法吧?我的意思是,是否有可能放弃对基于类的组件的支持。 @zaidfazil 您还在寻找什么其他方式?您可以改为创建一个包装器组件,该组件访问钩子并将道具传递给类组件。您的第二个评论/问题是什么,“是否有可能放弃对基于类的组件的支持?”您是否遇到应用此解决方案未按预期工作的特定问题? @zaidfazil 不是真的。 RRDv6 更高级别的路由器都维护自己的内部history
对象,并且仅通过从useNavigate
钩子返回的navigate
函数公开命令式导航。除了将类组件转换为函数组件之外,我知道的另一种选择是创建一个custom router 组件,这样您就可以直接使用自定义的history
对象。这将删除 history
作为传递的道具,并且需要使用包装器或 HOC。
感谢@Drew 的友好和非常详细的解释。我现在意识到了,我的问题很愚蠢。就我而言,这是一种误解或 TBH 较少的理解。再次感谢您对我的包容。我现在明白了,如何使用 v6 和我的代码库来处理功能组件。以上是关于以编程方式重定向到反应路由器 v6 中的路由的问题的主要内容,如果未能解决你的问题,请参考以下文章
登录页面后反应路由器 v6 不会切换到主页:警告:无法对未安装的组件执行 React 状态更新
React Router Dom v6 - 重定向到另一个路由
React Router Dom v6 - 重定向到另一个路由