You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Router v6编程式路由重定向问题求助——点击添加联系人按钮提交后跳转首页时报错TypeError

Fixing the TypeError: Cannot read properties of undefined (reading 'push') in React Router v6

Hey there! Let's break down why you're hitting this error and fix it step by step. The issue stems from two key mismatches with how React Router v6 works, especially with class components:

  1. Hooks don't work in class components: You imported useNavigate (a React Hook) but are using it in a class-based AddContacts component—hooks only function in function components or custom hooks, so that import is currently doing nothing.
  2. Navigation syntax changed in v6: Older React Router versions passed a history prop with a push method to components, but v6 uses a navigate function instead, and class components don't get this function automatically passed as a prop.

React Router v6 is designed to work seamlessly with function components, so this is the most idiomatic fix. Here's how to rewrite your component:

import React, { useState } from "react";
import { Consumer } from "../../context";
import TextInputGroup from "../layout/TextInputGroup";
import { v4 as uuidv4 } from "uuid";
import { useNavigate } from "react-router-dom";

function AddContacts() {
  const [state, setState] = useState({
    name: "",
    email: "",
    phone: "",
    errors: {},
  });
  const navigate = useNavigate(); // Get the navigate function from the hook

  const onSubmit = (dispatch, e) => {
    e.preventDefault();
    const { name, email, phone } = state;

    // Check for errors
    if (name === "") {
      setState(prev => ({ ...prev, errors: { name: "Name is required" } }));
      return;
    }
    if (email === "") {
      setState(prev => ({ ...prev, errors: { email: "Email is required" } }));
      return;
    }
    if (phone === "") {
      setState(prev => ({ ...prev, errors: { phone: "Phone is required" } }));
      return;
    }

    const newContact = {
      id: uuidv4(),
      name,
      email,
      phone,
    };

    dispatch({ type: "ADD_CONTACT", payload: newContact });

    // Reset form state
    setState({
      name: "",
      email: "",
      phone: "",
      errors: {},
    });

    // Navigate to homepage
    navigate("/");
  };

  const onChange = (e) => {
    setState(prev => ({
      ...prev,
      [e.target.name]: e.target.value
    }));
  };

  const { name, email, phone, errors } = 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={(e) => onSubmit(dispatch, e)}>
                <TextInputGroup
                  label="Name"
                  name="name"
                  placeholder="Enter Name..."
                  value={name}
                  onChange={onChange}
                  error={errors.name}
                />
                <TextInputGroup
                  label="Email"
                  name="email"
                  type="email"
                  placeholder="Enter Email..."
                  value={email}
                  onChange={onChange}
                  error={errors.email}
                />
                <TextInputGroup
                  label="Phone"
                  name="phone"
                  placeholder="Enter Phone..."
                  value={phone}
                  onChange={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;

Key changes here:

  • Switched from a class component to a function component
  • Used useState for state management instead of this.state/this.setState
  • Added useNavigate to access the navigation function
  • Replaced this.props.navigate.push("/") with navigate("/") (the v6 syntax for navigation)

Solution 2: Keep the Class Component with a Custom withRouter HOC

If you prefer to keep using a class component, you can create a simple higher-order component (HOC) to inject the navigate function into your component's props:

Step 1: Create the withRouter HOC

Add this somewhere in your project (e.g., a utils/withRouter.js file):

import { useNavigate } from 'react-router-dom';

export const withRouter = (Component) => {
  const Wrapper = (props) => {
    const navigate = useNavigate();
    return <Component navigate={navigate} {...props} />;
  };
  return Wrapper;
};

Step 2: Update AddContacts.js

  • Import the withRouter HOC
  • Wrap your component when exporting
  • Update the navigation call in onSubmit

Modified code snippets:

// Add the import at the top
import { withRouter } from "../../utils/withRouter";

// ... rest of your class component code ...

// Update the onSubmit handler's navigation line
this.props.navigate("/"); // No more .push()

// Wrap the component on export
export default withRouter(AddContacts);

Quick Route Fix in App.js

Also, note that your route for AddContacts has an unnecessary /*—unless you have nested routes under /contact/add, you can simplify it to:

<Route path="/contact/add" element={<AddContacts />} />

内容的提问来源于stack exchange,提问作者Oli Ullah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 00:07:35