Vercel部署后API请求React组件生产环境失效求助
问题:Vercel部署后无法获取Bored API内容,本地环境正常
问题情况
- 本地
localhost:3000环境下,组件可正常调用Bored API获取并渲染活动内容 - 通过Vercel从GitHub自动部署到生产环境后,点击"Get Activity"按钮无法加载活动内容
- 目标API无需密钥验证
原组件代码
import React, { useState, useEffect } from "react"; function Activities() { const [activity, setActivity] = useState(null); useEffect(() => { const storedActivity = localStorage.getItem("activity"); if (storedActivity) { setActivity(storedActivity); } }, []); const handleButtonClick = async () => { try { const response = await fetch("http://www.boredapi.com/api/activity/"); const data = await response.json(); setActivity(data.activity); localStorage.setItem("activity", data.activity); } catch (error) { console.error(error); } }; return ( <div className="flex h-fit sticky flex-col items-center bg-opacity-40 bg-white top-[80px] rounded-lg text-black text-center border-b border-gray-600"> <div className="flex flex-col py-2 px-6 h-[150px] w-[200px] overflow-hidden"> <button className="bg-green-500 hover:shadow-xl text-white font-bold py-2 px-6 mb-2 rounded focus:outline-none focus:ring-2 focus:ring-green-600" onClick={handleButtonClick} > Get Activity </button> <span className="text-sm text-black lg:text-base xl:text-lg">{activity}</span> </div> </div> ); } export default Activities;
问题原因
生产环境的Vercel站点默认使用HTTPS协议,但代码中调用的API地址是HTTP协议(http://www.boredapi.com/api/activity/)。现代浏览器出于安全策略,会阻止HTTPS页面加载HTTP资源(混合内容拦截),导致API请求被浏览器拦截,无法获取数据。
解决方案
- 修改API协议为HTTPS:将请求地址的
http://替换为https://,Bored API支持HTTPS访问 - 增强错误提示:在catch块中添加用户可见的错误信息,方便排查问题
- 可选:添加loading状态:提升用户交互体验
修改后的组件代码
import React, { useState, useEffect } from "react"; function Activities() { const [activity, setActivity] = useState(null); const [isLoading, setIsLoading] = useState(false); const [errorMsg, setErrorMsg] = useState(""); useEffect(() => { const storedActivity = localStorage.getItem("activity"); if (storedActivity) { setActivity(storedActivity); } }, []); const handleButtonClick = async () => { setIsLoading(true); setErrorMsg(""); try { // 改为HTTPS协议 const response = await fetch("https://www.boredapi.com/api/activity/"); if (!response.ok) { throw new Error(`请求失败: ${response.status}`); } const data = await response.json(); setActivity(data.activity); localStorage.setItem("activity", data.activity); } catch (error) { console.error(error); setErrorMsg("获取活动失败,请稍后重试"); } finally { setIsLoading(false); } }; return ( <div className="flex h-fit sticky flex-col items-center bg-opacity-40 bg-white top-[80px] rounded-lg text-black text-center border-b border-gray-600"> <div className="flex flex-col py-2 px-6 h-[150px] w-[200px] overflow-hidden"> <button className="bg-green-500 hover:shadow-xl text-white font-bold py-2 px-6 mb-2 rounded focus:outline-none focus:ring-2 focus:ring-green-600" onClick={handleButtonClick} disabled={isLoading} > {isLoading ? "加载中..." : "Get Activity"} </button> {errorMsg && <span className="text-sm text-red-600 mb-2">{errorMsg}</span>} <span className="text-sm text-black lg:text-base xl:text-lg">{activity}</span> </div> </div> ); } export default Activities;
内容的提问来源于stack exchange,提问作者Jerm
相关产品推荐
相关产品推荐

