React组件history.push失效及this属性异常问题求助
嘿,我来帮你搞定这些问题,咱们一步步来:
问题根源分析
你遇到的核心问题是你的组件没有获取到React Router提供的history对象,同时还有PropTypes校验的错误配置,导致了一系列异常。
具体解决方案
1. 让组件拿到history对象
React Router不会随便给普通组件注入history,只有两种情况组件能拿到这个对象:
- 组件直接作为
<Route>的component/render属性渲染 - 用
withRouter高阶组件包裹你的组件
推荐用withRouter的方式,步骤如下:
首先导入withRouter:
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { withRouter } from 'react-router-dom'; // 新增这行
然后在导出组件的时候用它包裹:
// 把原来的export default myComponent;改成下面这样 export default withRouter(myComponent);
这样你的组件就能通过this.props.history访问到路由历史对象,调用push方法跳转就正常了。
2. 修正PropTypes的错误配置
你现在把history的类型设成了PropTypes.string,这完全错了——history是一个包含push、replace等方法的对象。正确的校验方式有两种:
方式一:使用React Router官方的PropTypes
import { PropTypes as RouterPropTypes } from 'react-router-dom'; myComponent.propTypes = { history: RouterPropTypes.history.isRequired, };
方式二:手动定义对象形状
如果你不想额外导入路由的PropTypes,也可以自己写:
myComponent.propTypes = { history: PropTypes.shape({ push: PropTypes.func.isRequired, replace: PropTypes.func.isRequired, // 其他你需要用到的方法也可以加进来 }).isRequired, };
另外,你设置的defaultProps里把history设成'/'也不合理,直接删掉就行——用withRouter包裹后,路由会自动传入合法的history对象,不需要默认值。
3. 关于console.log(this)里props/context/ref为空的问题
如果你的组件没有接收外部传入的自定义props,也没使用context和ref,那这些字段为空是正常的。当你用withRouter包裹后,this.props里就会出现history、location、match这些路由相关的属性了。
4. 测试重定向功能
完成上面的步骤后,点击按钮调用this.props.history.push()应该就能正常跳转了。注意你写的路径params/${this.state.myParam}/?myQuery=${this.state.myQuery},要确保你的路由配置里有对应的匹配规则,比如:
<Route path="/params/:myParam" component={YourTargetComponent} />
这样跳转后才能正确渲染目标组件。
内容的提问来源于stack exchange,提问作者GuillaumeRZ

