React自定义Hook useFetch报错:JSON解析异常求助
useFetch Hook 出现
SyntaxError: Unexpected token '<' 的原因与解决方法 错误含义
这个错误直白点说:你的Fetch请求没拿到预期的JSON数据,反而收到了HTML页面(比如开头是<doctype html>的网页)。通常是请求过程中出了问题,导致服务器返回错误页面而非API的JSON响应。
常见原因及排查修复步骤
1. 跨域请求被拦截(CORS问题)
浏览器直接访问API时可能因为API本身支持跨域,但React本地开发环境(比如localhost:3000)不在API的允许列表里,浏览器会拦截响应,此时服务器可能返回错误页面替代正常JSON。
- 排查:打开浏览器控制台的「Network」面板,看请求的状态码和响应内容。如果是403/500状态,或者响应预览是HTML,基本就是跨域的锅。
- 解决:
- 开发环境下,在React项目的
package.json里加一行"proxy": "你的API域名"(比如"proxy": "https://api.example.com"),让请求通过开发服务器转发。 - 或者让API服务器配置CORS,允许你的前端域名访问。
- 开发环境下,在React项目的
2. 请求URL写错了
比如你用了相对路径/api/data但没配置代理,请求会打到React开发服务器(localhost:3000/api/data),而不是目标API,服务器返回的是React的首页index.html,自然会触发这个错误。
- 排查:看Network面板里的请求地址,确认是不是目标API的正确地址。
- 解决:要么用完整的API地址,要么配置代理后再用相对路径。
3. Fetch请求配置有遗漏
- 没设置
Accept: application/json请求头,服务器可能默认返回HTML而非JSON。 - 直接调用
response.json()但响应不是JSON,就会抛出错误。应该先检查响应状态是否正常,再解析。
修正后的useFetch Hook示例
import { useState, useEffect } from 'react'; const useFetch = (url, options = {}) => { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { setLoading(true); try { // 合并默认请求头,强制要求返回JSON const fetchOptions = { headers: { 'Accept': 'application/json', ...options.headers, }, ...options, }; const response = await fetch(url, fetchOptions); // 先判断响应是否正常 if (!response.ok) { throw new Error(`请求失败: ${response.status} ${response.statusText}`); } const result = await response.json(); setData(result); setError(null); } catch (err) { setError(err.message); // 可以打印响应内容排查是不是HTML if (err.response) console.error('响应内容:', await err.response.text()); } finally { setLoading(false); } }; fetchData(); }, [url, options]); return { data, loading, error }; }; export default useFetch;
TestUseFetch组件注意事项
确保传入的URL是正确的,比如:
import useFetch from './useFetch'; const TestUseFetch = () => { const { data, loading, error } = useFetch('https://api.example.com/your-endpoint'); if (loading) return <div>加载中...</div>; if (error) return <div>出错了: {error}</div>; return <div>{JSON.stringify(data)}</div>; }; export default TestUseFetch;
内容的提问来源于stack exchange,提问作者ambiasm
相关产品推荐
相关产品推荐

