React表单触发Axios Get请求后无法更新State,寻求解决方案
解决React中调用Google Places API后无法更新State的问题
首先,咱们先拆解下你遇到的核心问题,再一步步给出解决办法:
1. 核心问题:mode: "no-cors"导致无法读取响应数据
你在axios请求里加了mode: "no-cors",这会让浏览器完全限制你访问响应内容——哪怕请求成功,你也拿不到response.data,自然没法通过setState更新数据。这是你没法更新state的主要原因。
但直接去掉mode: "no-cors"又会遇到CORS跨域错误,因为Google Places API默认不允许前端直接跨域请求。这里有两个靠谱的解决方案:
方案一:使用官方Google Places JavaScript SDK(推荐)
Google专门提供了前端可用的Places SDK,完全避开CORS问题,用法如下:
- 在你的
public/index.html里引入SDK脚本(替换成你的API Key):
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_API_KEY&libraries=places"></script>
- 修改你的
handleSubmit函数,用SDK的TextSearchService替代axios:
handleSubmit(event) { event.preventDefault(); // 实例化Places搜索服务 const placesService = new window.google.maps.places.TextSearchService(); placesService.textSearch( { query: `attractions in ${this.state.city}` }, (results, status) => { if (status === window.google.maps.places.PlacesServiceStatus.OK) { // 成功获取结果后更新state this.setState({ sights: results }); console.log('获取到景点数据:', results); } else { console.error('请求失败:', status); } } ); }
方案二:搭建后端代理(适合必须用axios的场景)
如果一定要用axios请求,你需要自己搭一个后端代理接口,让后端去请求Google API,前端再调用自己的后端接口,这样就绕开了CORS限制:
- 举个Node.js/Express的代理示例:
const express = require('express'); const axios = require('axios'); const app = express(); const PORT = 5000; // 代理接口 app.get('/api/places', async (req, res) => { const { city } = req.query; const apiKey = 'YOUR_GOOGLE_API_KEY'; try { const response = await axios.get( `https://maps.googleapis.com/maps/api/place/textsearch/json?query=attractions+in+${city}&key=${apiKey}` ); res.json(response.data); } catch (err) { res.status(500).json({ error: err.message }); } }); app.listen(PORT, () => console.log(`代理服务运行在端口 ${PORT}`));
- 前端修改axios请求地址:
handleSubmit(event) { event.preventDefault(); axios.get(`http://localhost:5000/api/places?city=${this.state.city}`) .then(response => { this.setState({ sights: response.data.results }); }) .catch(err => console.log('请求出错:', err)); }
2. 其他优化点
- state初始值调整:你把
sights初始设为{},但API返回的是数组,建议改成sights: [],这样后续渲染时用map遍历不会报错。 - 多余的ResultContainer组件:你render里写了两个
<ResultContainer />,第二个没传sights属性,要么删掉多余的,要么统一传参。 - 关于componentDidMount的误解:你提到
componentDidMount()无法绑定handleSubmit——其实事件处理函数的绑定本来就不该放在componentDidMount里,你在constructor里的绑定方式是完全正确的,这部分没问题。
按照上面的方法调整后,应该就能正常更新state并渲染数据了。
内容的提问来源于stack exchange,提问作者Scott B
相关产品推荐
相关产品推荐

