React项目使用Axios获取数据失败,请求排查问题
解决你的React + Axios数据渲染问题
我帮你梳理下代码里的几个关键问题,逐个修复后就能正常渲染数据了:
1. 组件类名拼写错误
你写的React.component应该是**React.Component**(注意Component的首字母大写),这是React类组件的标准写法,小写会直接导致组件无法正确初始化。
2. Axios请求中this指向丢失
在axios.get().then()里用普通函数的话,this会脱离组件实例的上下文,不仅this.setState会失效,还会导致this.props.source读取异常——这也是你看到Cannot read property 'protocol' of undefined错误的核心原因。把then的回调改成箭头函数就能保留组件的this指向:
componentDidMount () { this.serverRequest = axios.get(this.props.source) .then(result => { // 箭头函数绑定组件的this this.setState({ jobs: result.data.jobs }); }) .catch(err => { // 建议加上错误捕获,方便调试 console.error('请求出错:', err); }) }
3. ReactDOM渲染的DOM选择器错误
document.getElementById('#root')里多了CSS选择器的#,getElementById只需要传入ID名称,改成:
ReactDOM.render(<App source="你的JSON地址"/>, document.getElementById('root'));
4. 组件卸载时的请求取消方式错误
原来的this.serverRequest.abort()是原生XHR的写法,Axios的请求取消需要用专属的CancelToken机制,修正如下:
constructor (props) { super(props); this.state = { jobs: [] }; // 创建请求取消令牌 this.cancelTokenSource = axios.CancelToken.source(); } componentDidMount () { this.serverRequest = axios.get(this.props.source, { cancelToken: this.cancelTokenSource.token // 绑定令牌到请求 }) .then(result => { this.setState({ jobs: result.data.jobs }); }) .catch(err => { if (axios.isCancel(err)) { console.log('请求已取消:', err.message); } else { console.error('请求出错:', err); } }) } componentWillUnmount () { // 触发请求取消 this.cancelTokenSource.cancel('组件卸载,取消请求'); }
5. 列表渲染的小优化
在map渲染列表时,用箭头函数更简洁,也能避免额外的this问题:
{this.state.jobs.map(job => ( <div key={job.url} className="job"> <a href={job.url} target="_blank" rel="noopener noreferrer"> {job.company_name} is looking for a {job.term} {job.title} </a> </div> ))}
完整修正后的代码
<!-- DOCTYPE HTML --> <html> <head> <title>Your First React Project</title> <link rel="stylesheet" type="text/css" href="app.css"> <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> </head> <body> <div id="root"></div> <script type="text/babel"> class App extends React.Component { constructor (props) { super(props); this.state = { jobs: [] }; this.cancelTokenSource = axios.CancelToken.source(); } componentDidMount () { this.serverRequest = axios.get(this.props.source, { cancelToken: this.cancelTokenSource.token }) .then(result => { this.setState({ jobs: result.data.jobs }); }) .catch(err => { if (axios.isCancel(err)) { console.log('请求已取消:', err.message); } else { console.error('请求出错:', err); } }) } componentWillUnmount () { this.cancelTokenSource.cancel('组件卸载,取消请求'); } render () { return ( <div> <h1>Jobs!</h1> {this.state.jobs.map(job => ( <div key={job.url} className="job"> <a href={job.url} target="_blank" rel="noopener noreferrer"> {job.company_name} is looking for a {job.term} {job.title} </a> </div> ))} </div> ) } } ReactDOM.render(<App source="https://gist.githubusercontent.com/rohan-paul/b74bf6ef1adfdb92e0af5783e6c93a71/raw/bdffbbcb50128c03dd9edc90dbeb85e88c70ebc4/jobs.json"/>, document.getElementById('root')); </script> </body> </html>
现在运行代码应该就能正常展示职位列表了,开发时记得多留意浏览器控制台的错误提示,能帮你更快定位问题~
内容的提问来源于stack exchange,提问作者Rohan_Paul
相关产品推荐
相关产品推荐

