React中Ajax请求出现Uncaught (in promise) TypeError问题求助
问题分析与解决方案
你遇到的Uncaught (in promise) TypeError: Cannot read property of undefined错误,核心原因是Promise的then回调里的this指向不对——你用了普通函数作为then的回调,这个函数里的this默认绑定的是全局对象(浏览器里是window),而不是你的React组件实例,所以自然找不到this.showBattersData方法。
第一步:修复this指向问题
有三种简单的方式可以解决这个问题:
1. 使用箭头函数(推荐)
箭头函数会继承外层作用域的this,也就是你的组件实例:
battersDataFetchReq() { fetchFactory('./assets/some.json', 'GET') .then((data) => { // 这里改成箭头函数 this.showBattersData(data); }) }
2. 提前保存this到变量
在then之前把组件的this存到一个变量里,比如self,然后在回调里用这个变量:
battersDataFetchReq() { const self = this; // 保存组件的this fetchFactory('./assets/some.json', 'GET') .then(function(data) { self.showBattersData(data); // 用self代替this }) }
3. 用bind绑定this到回调函数
直接给回调函数绑定组件的this:
battersDataFetchReq() { fetchFactory('./assets/some.json', 'GET') .then(function(data) { this.showBattersData(data); }.bind(this)) // 绑定组件的this }
第二步:优化React数据管理(重要)
你的代码里用了全局变量rowdata和batters来存储数据,这在React里是不推荐的——React不会监听全局变量的变化,就算你成功获取到数据,页面也不会自动更新渲染表格。正确的做法是用组件的state来管理数据:
修改后的完整代码:
import React, {Component} from 'react' import { fetchFactory } from '../Fetch/fetchFactory' export class Body extends React.Component { constructor(props) { super(props); this.battersDataFetchReq = this.battersDataFetchReq.bind(this); this.showBattersData = this.showBattersData.bind(this); // 初始化state存储batters数据 this.state = { batters: [] }; this.battersDataFetchReq(); } battersDataFetchReq() { fetchFactory('./assets/some.json', 'GET') .then((data) => { // 用箭头函数解决this问题 this.showBattersData(data); }) // 别忘了加catch处理请求错误! .catch(err => console.error('请求失败:', err)) } showBattersData(res) { console.log("inside showBattersData:: ", res); // 更新state,React会自动触发重新渲染 this.setState({ batters: res.batters.batter }); } render() { const { batters } = this.state; return ( <div> <table id="batters" name="batters" className="table table-bordered table-hover"> <caption>List of batters</caption> <thead> <tr> <th>#</th> <th>Id</th> <th>Type</th> </tr> </thead> <tbody id="batters_body"> {/* 用map动态生成表格行,注意加key */} {batters.map((batter, index) => ( <tr key={batter.id}> <td>{index + 1}</td> <td>{batter.id}</td> <td>{batter.type}</td> </tr> ))} </tbody> </table> </div> ); } }
额外注意点:
- React里HTML的
class属性要写成className,因为class是JavaScript的关键字; - 用
map渲染列表时,必须给每个元素加唯一的key属性(这里用batter.id是最佳选择); - 永远不要忘记给Promise加
catch处理请求错误,避免未捕获的Promise错误; - 不要用拼接HTML字符串的方式生成DOM,React推荐用JSX语法,更安全也更易维护。
内容的提问来源于stack exchange,提问作者Nakul Nagariya
相关产品推荐
相关产品推荐

