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

React类组件this.props为空及history.push报错问题求助

解决React路由跳转报错:TypeError: undefined is not an object (evaluating 'this.props.history.push')

你的问题核心是react-router-dom版本适配问题:你当前使用的是v6版本,但代码仍沿用v5的this.props.history.push写法。v6中,通过<Route element={<Component />}>渲染的组件不会自动接收history、location等路由props,因此this.props为空对象,导致跳转失败。以下是两种适配v6的解决方案:

方案一:用withRouter包装类组件(适配现有类组件写法)

react-router-dom v6保留了withRouter高阶组件,可给类组件注入路由能力:

  1. 在RoomJoinPage.js中导入withRouter:
import { Link, withRouter } from 'react-router-dom'; // 新增withRouter
  1. 修改组件导出方式,用withRouter包装:
// 替换原直接导出类的写法
class RoomJoinPage extends Component {
  // 原组件内部代码保持不变
}

export default withRouter(RoomJoinPage); // 用withRouter包装后导出
  1. 替换跳转逻辑,v6中用this.props.navigate替代history.push:
roomButtonPress(e) {
  const requestOptions = {
      method: "POST",
      headers: {"Content-Type": "application/json" },
      body: JSON.stringify({
          code: this.state.roomCode
      })
  };
  fetch('/api/join-room', requestOptions)
  .then((response) => {
      if (response.ok) {
          this.props.navigate(`/room/${this.state.roomCode}`); // 替换为navigate
      }
      else {
          this.setState({error: "Room not found."})
      }
  })
  .catch((error) => {
      console.log(error); 
  });
}

方案二:转为函数组件(v6推荐写法)

函数组件配合useNavigate钩子是v6的推荐方案,代码更简洁:

改写后的RoomJoinPage.js:

import React, { useState } from 'react';
import { Button, Grid, Typography, TextField } from '@mui/material';
import { Link, useNavigate } from 'react-router-dom';

export default function RoomJoinPage() {
  const [roomCode, setRoomCode] = useState("");
  const [error, setError] = useState("");
  const navigate = useNavigate(); // 获取路由跳转函数

  const handleTextFieldChange = (e) => {
    setRoomCode(e.target.value);
  };

  const roomButtonPress = (e) => {
    const requestOptions = {
      method: "POST",
      headers: {"Content-Type": "application/json" },
      body: JSON.stringify({ code: roomCode })
    };
    fetch('/api/join-room', requestOptions)
    .then((response) => {
      if (response.ok) {
        navigate(`/room/${roomCode}`); // 直接调用navigate跳转
      } else {
        setError("Room not found.");
      }
    })
    .catch((error) => {
      console.log(error); 
    });
  };

  return (
    <Grid container spacing={1}>
      <Grid item xs={12} align="center">
        <Typography variant='h4' component="h4">
          Join a Room
        </Typography>
      </Grid>
      <Grid item xs={12} align="center">
        <TextField 
          error={error}
          label="Code"
          placeholder="Enter a room code"
          value={roomCode}
          helperText={error}
          variant="outlined"
          onChange={handleTextFieldChange}
        />
      </Grid>
      <Grid
        container
        spacing={1}
        style={{width: "100%", padding: 10}}
        direction="column"
        alignItems="center"
        justifyContent="center"
        alignContent="center"
      >
        <Grid item xs={12}>
          <Button variant='contained' color='secondary' onClick={roomButtonPress}>Enter room</Button>
        </Grid>
        <Grid item xs={12}>
          <Button variant='contained' color='primary' to='/' component={Link}>Back</Button>
        </Grid>
      </Grid>
    </Grid>
  );
}

额外优化:HomePage替换a标签为Link组件

你HomePage中的<a href='./join'>会触发页面刷新,不符合单页应用逻辑,建议换成react-router-dom的Link组件:

<Route exact path='/' element={
  <div>
    <h1>This is the home page</h1>
    <Link to='/join'>Link to room join page</Link>
    <br/><Link to='/create'>Link to room create page</Link>
    <br/><a href='/api/home'>API?</a> {/* 后端接口链接保留a标签即可 */}
  </div>
}></Route>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:24:32