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

React Redux类组件TypeError:无法读取undefined的params属性解决方法

问题:TypeError: Cannot read properties of undefined (reading 'params')

尝试通过id获取用户详情数据时出现上述错误,相关代码如下:

app.js

import React, { Component } from 'react'
import Jumbotron from './component/Jumbotron'
import NavbarComponent from './component/NavbarComponent'

import {
  BrowserRouter,
  Route,
  Routes,
} from "react-router-dom";

import HomeContainer from './container/HomeContainer';
import CreateUserContainer from './container/CreateUserContainer';
import EditUserContainer from './container/EditUserContainer';
import DetailUserContainer from './container/DetailUserContainer';

export default class App extends Component {
  render() {
    return (
      <div>
        <BrowserRouter>
          <NavbarComponent />
          <Jumbotron />
          <Routes>
            <Route path='/' element={<HomeContainer/>} exact />
            <Route path='/create' element={<CreateUserContainer />} exact />
            <Route path='/edit/:id' element={<EditUserContainer />} exact />
            <Route path='/detail/:id' element={<DetailUserContainer />} exact />
          </Routes>
        </BrowserRouter>
      </div>
    )
  }
}

container/DetailUserContainer.js

import React, { Component } from 'react'
import { Container } from 'react-bootstrap'
import { connect } from 'react-redux';
import { getDetailUser } from '../actions/UserAction';

class DetailUserContainer extends Component {
  
  componentDidMount(){
    this.props.dispatch(getDetailUser(this.props.match.params.id));
  }
  
  render() {
    return (
      <div>
        <Container className='pt-3'>
          <div>
            <h1>Detail</h1>
          </div>
        </Container>
      </div>
    )
  }
}

export default connect()(DetailUserContainer)

reducers/users.js

import { GET_LIST_USERS, GET_DETAIL_USERS } from "../actions/UserAction";

let initialState = {
    getUsers: false,
    errorGetUser: false,
    // DETAIL USER
    getDetailUsers: false,
    errorGetDetailUser: false
}

const users = (state = initialState, action) => {
    switch (action.type) {
        case GET_LIST_USERS:
            return {
                ...state,
                getUsers: action.payload.data,
                errorGetUser: action.payload.errorMessage
            };
        case GET_DETAIL_USERS:
            return {
                ...state,
                getDetailUsers: action.payload.data,
                errorGetDetailUser: action.payload.errorMessage
            };
        default:
            return state;
    }
}

export default users;

actions/UserAction.js

import React from 'react'
import axios from 'axios'

export const GET_LIST_USERS = "GET_LIST_USERS"
export const GET_DETAIL_USERS = "GET_DETAIL_USERS"

// GET USER
export const getListUser= () => {
  return (dispatch) => {
    axios.get('https://my-json-server.typicode.com/baihaqiyazid/database/users')
      .then(function (response) {
        dispatch({
          type: GET_LIST_USERS,
          payload: {
            data: response.data,
            errorMessage: false
          }
        })
      })
      .catch(function (error) {
        dispatch({
          type: GET_LIST_USERS,
          payload: {
            data: false,
            errorMessage: error.message
          }
        })
      })
  }
}

// DETAIL USER
export const getDetailUser= (id) => {
  return (dispatch) => {
    axios.get('https://my-json-server.typicode.com/baihaqiyazid/database/users/' + id)
      .then(function (response) {
        dispatch({
          type: GET_DETAIL_USERS,
          payload: {
            data: response.data,
            errorMessage: false
          }
        })
      })
      .catch(function (error) {
        dispatch({
          type: GET_DETAIL_USERS,
          payload: {
            data: false,
            errorMessage: error.message
          }
        })
      })
  }
}

reducers/index.js

import { combineReducers } from 'redux'
import users from './users'

export default combineReducers({
    users
})

解决方案

错误原因

你使用的是React Router v6,该版本中Route组件的element属性接收的组件不再自动注入match、location、history等路由相关props,因此this.props.match为undefined,读取params时触发报错。

方案1:封装自定义withRouter高阶组件(适配类组件)

React Router v6移除了官方withRouter,可自行封装一个将路由props注入类组件:

  1. 创建withRouter.js文件:
import { useParams, useLocation, useNavigate } from 'react-router-dom';

const withRouter = (Component) => {
  const Wrapper = (props) => {
    const params = useParams();
    const location = useLocation();
    const navigate = useNavigate();
    return <Component {...props} match={{ params }} location={location} navigate={navigate} />;
  };
  return Wrapper;
};

export default withRouter;
  1. 修改DetailUserContainer.js,用withRouter包裹连接Redux后的组件:
import React, { Component } from 'react'
import { Container } from 'react-bootstrap'
import { connect } from 'react-redux';
import { getDetailUser } from '../actions/UserAction';
import withRouter from '../withRouter'; // 引入自定义withRouter

class DetailUserContainer extends Component {
  
  componentDidMount(){
    this.props.dispatch(getDetailUser(this.props.match.params.id));
  }
  
  render() {
    return (
      <div>
        <Container className='pt-3'>
          <div>
            <h1>Detail</h1>
          </div>
        </Container>
      </div>
    )
  }
}

// 先connect再用withRouter包裹
export default withRouter(connect()(DetailUserContainer));

方案2:改为函数组件,使用useParams钩子(推荐)

React Router v6更推荐函数组件配合路由钩子,写法更简洁:

修改DetailUserContainer.js为函数组件:

import React, { useEffect } from 'react'
import { Container } from 'react-bootstrap'
import { connect } from 'react-redux';
import { getDetailUser } from '../actions/UserAction';
import { useParams } from 'react-router-dom';

const DetailUserContainer = (props) => {
  const { id } = useParams(); // 获取路由参数id
  
  useEffect(() => {
    props.dispatch(getDetailUser(id));
  }, [id, props.dispatch])
  
  return (
    <div>
      <Container className='pt-3'>
        <div>
          <h1>Detail</h1>
        </div>
      </Container>
    </div>
  )
}

export default connect()(DetailUserContainer)

两种方案均可解决问题,方案2更符合React Router v6的设计趋势,建议优先采用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 09:18:29