React类组件使用useParams获URL参数报Invalid hook call错误如何解决
问题原因
useParams 是 React Router 提供的Hook API,仅支持在函数组件的顶层作用域中调用,你的代码在类组件的handleReservation方法内调用Hook,不符合Hook的使用规则,因此触发Hooks can only be called inside of the body of a function component报错。
解决方案
方案1:通过高阶组件封装给类组件传递路由参数
如果你需要保留类组件写法,可以自定义高阶组件包裹你的类组件,将路由参数通过props注入:
import { useParams } from 'react-router-dom'; // 自定义高阶组件,将params注入到被包裹组件的props中 function withParams(Component) { return props => <Component {...props} params={useParams()} />; }
之后修改你的SimpleMap组件逻辑:
- 删掉
handleReservation方法内的let params = useParams();这行代码 - 取参数改为
this.props.params.serviceID - 导出组件时用高阶组件包裹:
export default withParams(SimpleMap);
方案2:将类组件改写为函数组件(更推荐)
目前React官方更推荐使用函数组件配合Hook开发,改写后的代码示例如下:
import { useParams } from 'react-router-dom'; import { useState } from 'react'; import axios from 'axios'; import Cookies from 'js-cookie'; // 其余依赖导入保持和原代码一致 const AnyReactComponent = ({ text }) => <div>{<LocationOnIcon color="primary"/>}</div>; const SimpleMap = (props) => { const [resdate, setResdate] = useState(new Date().toISOString().substr(0,10)); const params = useParams(); // 直接在函数组件顶层调用useParams const handleReservation = async () => { await axios({ method: 'post', url: 'http://localhost:3001/reservation', headers: {}, data: { serviceID: params.serviceID, userID: Cookies.get('userID'), reservationDate: resdate } }) }; return ( <div style={{ height: '50vh', width: '35%', justifyContent: 'flex-end' }}> <GoogleMapReact bootstrapURLKeys={{ key: 'apiKey' }} defaultCenter={ AnyReactComponent ? props.greatPlaceCoords: props.center} defaultZoom={props.zoom} lat={45.756659} lng={21.228703} > <AnyReactComponent {...props.greatPlaceCoords} text={<><LocationOnIcon/> location</>} /> </GoogleMapReact> <Button onClick={handleReservation}> Make a reservation </Button> <Booking/> </div> ); } SimpleMap.defaultProps = { center: { lat: 59.95, lng: 30.33 }, greatPlaceCoords: { lat:45.756659, lng:21.228703 }, zoom: 11, }; export default SimpleMap;
其他代码问题修正
你的原代码还存在2处语法错误:
Button组件标签未闭合,缺少结束的>和内容包裹标记AnyReactComponent的text属性赋值写法错误,不能把JSX写在字符串引号内
内容的提问来源于stack exchange,提问作者John Shelby
相关产品推荐
相关产品推荐

