以编程方式重定向到反应路由器 v6 中的路由的问题

Posted

技术标签:

【中文标题】以编程方式重定向到反应路由器 v6 中的路由的问题【英文标题】:Problem in redirecting programmatically to a route in react router v6 【发布时间】:2021-12-22 06:22:58 【问题描述】:

我想对某些用户操作执行导航,比如按钮的 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("/");

【讨论】:

以上是关于以编程方式重定向到反应路由器 v6 中的路由的问题的主要内容,如果未能解决你的问题,请参考以下文章

登录页面后反应路由器 v6 不会切换到主页:警告:无法对未安装的组件执行 React 状态更新

React Router Dom v6 - 重定向到另一个路由

React Router Dom v6 - 重定向到另一个路由

如何从索引页重定向到Gatsby.JS项目中以编程方式生成的路由

使用反应路由器重定向

反应路由器>重定向不起作用