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高阶组件,可给类组件注入路由能力:
- 在RoomJoinPage.js中导入withRouter:
import { Link, withRouter } from 'react-router-dom'; // 新增withRouter
- 修改组件导出方式,用withRouter包装:
// 替换原直接导出类的写法 class RoomJoinPage extends Component { // 原组件内部代码保持不变 } export default withRouter(RoomJoinPage); // 用withRouter包装后导出
- 替换跳转逻辑,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
相关产品推荐
相关产品推荐

