以编程方式重定向到反应路由器 v6 中的路由的问题 [英] Problem in redirecting programmatically to a route in react router v6

查看:28
本文介绍了以编程方式重定向到反应路由器 v6 中的路由的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想对某些用户操作执行导航,例如按钮的 onSubmit.假设用户单击添加联系人按钮,我希望 react-router 在/"中重定向这是主页.目前我正面临这个问题-->TypeError:无法读取未定义的属性(读取推送").作为初学者,我非常感谢专家的帮助.

AddContacts.js

import React, { Component } from "react";从../../context"导入{消费者};从../layout/TextInputGroup"导入 TextInputGroup;从uuid"导入 { v4 as uuidv4 };从react-router-dom"导入 { useNavigate };类 AddContacts 扩展组件 {状态 = {名称:",电子邮件:",电话:",错误:{},};onSubmit = (dispatch, e) =>{e.preventDefault();const { 姓名、电子邮件、电话 } = this.state;//检查错误if (name === "") {this.setState({ errors: { name: "Name is required" } });返回;}如果(电子邮件==="){this.setState({ errors: { email: "Email is required" } });返回;}如果(电话==="){this.setState({ errors: { phone: "Phone is required" } });返回;}常量新联系人 = {id: uuidv4(),名称,电子邮件,电话,};dispatch({ type: "ADD_CONTACT", payload: newContact });这个.setState({名称:",电子邮件:",电话:",错误:{},});this.props.navigate.push("/");};onChange = (e) =>this.setState({ [e.target.name]: e.target.value });使成为() {const { 姓名、电子邮件、电话、错误 } = this.state;返回 (<消费者>{(值) =>{常量 { 调度 } = 值;返回 (<div className="card mb-3"><div className="card-header">添加联系人</div><div className=""card-body"><form onSubmit={this.onSubmit.bind(this, dispatch)}><文本输入组标签=名称"名称=名称";placeholder=输入名称..."值={名称}onChange={this.onChange}错误={errors.name}/><文本输入组标签=电子邮件"名称=电子邮件";类型=电子邮件";placeholder=输入电子邮件..."价值={电子邮件}onChange={this.onChange}错误={errors.email}/><文本输入组标签=电话"名称=电话";placeholder=输入电话..."价值={电话}onChange={this.onChange}错误={errors.phone}/><输入类型=提交";value="添加联系人"className="btn btn-light btn-block mt-3"/></表格></div></div>);}}</消费者>);}}导出默认的 AddContacts;

这是 App.js 文件

import React, { Component } from "react";从react-router-dom"导入 { BrowserRouter, Routes, Route, Link };从./components/contacts/Contacts"导入联系人;从./components/layout/Header"导入标题;从./components/contacts/AddContacts"导入 AddContacts;从./components/pages/About"导入关于;从./context"导入{ Provider };导入bootstrap/dist/css/bootstrap.min.css";导入./App.css";函数应用程序(){返回 (<提供者><浏览器路由器><div className="App"><标题品牌=联系人经理"/><div className=容器"><路线><路由路径="/";element={<联系人/>}/>{""}<路由路径="/contact/add/*"element={<AddContacts/>}/>{""}<路线路径=约/*"元素={<关于/>}/>{""}</路线>{""}</div>{>"}</div>{>"}</BrowserRouter>{""}</提供者>);}导出默认应用程序;

解决方案

问题

<块引用>

TypeError:无法读取未定义的属性(读取推送")

这是因为您尝试从不存在的 navigate 道具导航,它是未定义的.

this.props.navigate.push("/");

useNavigate 钩子仅与功能组件兼容,因此您希望/需要将 navigate 与类组件一起使用,您必须转换 AddContacts 到函数组件,或滚动您自己的自定义 withRouter 高阶组件以注入路由道具";就像 react-router-dom v5.x 中的 withRouter HOC 一样.

解决方案

我不会介绍将类组件转换为函数组件.这是一个示例自定义 withRouter HOC:

const withRouter = WrappedComponent =>道具=>{常量导航 = useNavigate();//等等...其他 react-router-dom v6 钩子返回 (<包裹组件{...道具}导航={导航}//等等.../>);};

并用新的 HOC 装饰 AddContacts 组件.

export default withRouter(AddContacts);

现在这会将 navigate 道具(和您设置的任何其他道具)传递给装饰组件,并且 this.navigate 现在将是已定义.

此外,导航 API 从 v5 更改为 v6,不再使用直接的 history 对象.navigate 是一个函数而不是一个对象.要使用您调用函数并传递 1 或 2 个参数,第一个是目标路径,第二个是可选的选项";带有 replace 和/或 state 键/值的对象.

<块引用>

接口 NavigateFunction {(到:到,选项?:{替换?:布尔值;状态?:状态 }): 空白;(增量:数字):无效;}

现在如下导航:

this.props.navigate("/");

I want to perform navigation on certain user actions, say onSubmit of a button. suppose a user clicks on the Add contact button I want react-router to redirect in "/" which is the home page. At the moment I am facing this problem--> TypeError: Cannot read properties of undefined (reading 'push'). As a beginner, I would really appreciate experts' help.

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;

Here 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;

解决方案

Issue

TypeError: Cannot read properties of undefined (reading 'push')

This is cause by you attempting to navigate from a navigate prop that doesn't exist, it's undefined.

this.props.navigate.push("/");

The useNavigate hook is only compatible with function components, so of you want/need to use navigate with a class component you must either convert AddContacts to a function component, or roll your own custom withRouter Higher Order Component to inject the "route props" like the withRouter HOC from react-router-dom v5.x did.

Solution

I won't cover converting a class component to function component. Here's an example 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);

This will now pass a navigate prop (and any others you set up) to the decorated components and this.navigate will now be defined.

Additionally, the navigation API changed from v5 to v6, it's no longer the direct history object being used. navigate is a function instead of an object. To use you invoke the function and pass 1 or 2 arguments, the first is the target path, the second is an optional "options" object with replace and/or state key/values.

interface NavigateFunction {
  (
    to: To,
    options?: { replace?: boolean; state?: State }
  ): void;
  (delta: number): void;
}

To navigate now as follows:

this.props.navigate("/");

这篇关于以编程方式重定向到反应路由器 v6 中的路由的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆