React中将URL参数字符串转数组获取长度时报split未定义错误如何解决
问题原因
你遇到的TypeError: Cannot read property 'split' of undefined报错,核心原因是你调用split方法的movieData.seats是未定义值,具体有三个触发原因:
- hash路由参数解析错误:你用的是HashRouter模式,URL中的查询参数放在了
#符号后面,而this.props.location.search只能读取域名后、#前的查询参数,你当前场景下this.props.location.search是空值,queryString.parse拿到的是空对象,自然movieInfo.seats是undefined。 - 生命周期执行顺序问题:React组件生命周期中
render函数会早于componentDidMount执行,首次渲染时componentDidMount里的movieData = movieInfo还没执行,movieData本身就是未定义状态,直接读取movieData.seats必然报错。 - 不符合React的状态管理规范:你用全局变量
movieData存页面参数,而没有统一存在组件state里,容易出现变量初始化不同步的问题。
解决方案
步骤1:修正路由参数解析逻辑
修改componentDidMount里的参数解析代码,正确提取hash路径后的查询参数:
componentDidMount() { // 从hash中提取查询字符串部分 const hashContent = this.props.location.hash const queryStr = hashContent.includes('?') ? hashContent.split('?')[1] : '' const movieInfo = queryString.parse(queryStr) // 直接把参数存入state,不需要额外的全局movieData变量 this.setState(movieInfo) // 后面你的fetch逻辑不需要改,保持原样即可 const requestOptions = { method: 'GET', headers: { 'Content-Type': 'application/json', 'client_token': 'ebd86470-7e90-4ece-9e89-1b6d4d2cbb61' } }; fetch(`http://sandbox-api.com/v1/seat/prices?venue_id=90&movie_id=3232&showtime_id=2130&movie_date=2021-08-02`, requestOptions) .then(response => response.json()) .then((seatPrice) => { // 原有fetch回调逻辑保持不变 const filteredODCData = seatPrice.data.ticketPrices.priceList.filter(type => type.seatType.includes("ODC")); const adultPrice = filteredODCData[0].adultPrice; const childPrice= filteredODCData[0].childPrice; const filteredBoxData = seatPrice.data.ticketPrices.priceList.filter(type => type.seatType.includes("Box Seats - Ground Floor")); const adultBoxPrice = filteredBoxData[0].adultPrice; const advanceCommision = seatPrice.data.ticketPrices.advancedCommission; this.setState({ seatPrice: seatPrice.data.ticketPrices.priceList, adultPrice: adultPrice, childPrice: childPrice, adultBoxPrice: adultBoxPrice, advanceCommision: advanceCommision, dataLoaded: true, }) }).catch(console.log); }
步骤2:修改render逻辑,安全读取参数并拆分座位
不要用全局movieData变量,直接从state读取seats,并且加存在性判断,避免undefined调用split:
render () { // 从state中解构出所有需要用到的参数 const {seatPrice, dataLoaded, seats, adultPrice, childPrice, adultBoxPrice, advanceCommision} = this.state; // 安全拆分座位:如果seats存在就拆分,否则默认是空数组 const seatArray = seats ? seats.split(',') : [] // 直接获取数组长度就是座位个数 const seatCount = seatArray.length console.log('座位列表:', seatArray) console.log('座位数量:', seatCount) // 剩下的你的原有render逻辑写在这里即可 // ... }
原理说明
- 修正参数解析后,能正确拿到URL里的
seats参数存入state - 首次render时
seats还没赋值,我们给了默认空数组,不会触发undefined调用split的报错 - state更新后会触发组件重新render,第二次render时就能拿到正确的座位列表和数量
内容的提问来源于stack exchange,提问作者Ryan Fonseka
相关产品推荐
相关产品推荐

