为何res.text()在useEffect()中无法正常工作?
问题分析:useEffect内fetch请求在客户端无输出的原因
问题场景
在islands/test.tsx中编写了以下Preact组件代码:
import { useEffect } from "preact/hooks"; export default function Test(){ fetch('https://example.com') .then(res => res.text()) .then(d => console.log(d)) useEffect(() => { fetch('https://example.com') .then(res => res.text()) .then(d => console.log(d)) }) return 'hi' }
出现的现象:
- useEffect外部的fetch请求能在服务器控制台正常输出数据
- useEffect内部的fetch请求在客户端控制台无任何输出
但将请求目标替换为https://jsonplaceholder.typicode.com/todos/1并改用res.json()处理响应后,服务器和客户端控制台均能正常显示内容。
核心原因
1. 代码执行环境的本质差异
- useEffect外部的代码在服务器端渲染阶段执行:服务器端的
fetch不受浏览器的跨域(CORS)规则限制,只要目标服务器能正常响应,就能拿到数据并输出。 - useEffect内部的代码在客户端浏览器中执行:浏览器会强制校验跨域请求的合法性,只有目标服务器明确配置了允许当前域名的CORS响应头,请求才能顺利完成。
2. 目标服务器的CORS配置差异
https://example.com的服务器未配置允许跨域请求的响应头(如Access-Control-Allow-Origin),客户端浏览器会直接拦截该请求的响应,导致后续的then回调(包括console.log)完全无法执行。由于代码未添加catch捕获异常,控制台不会显示报错信息,只会在网络面板中看到跨域错误。https://jsonplaceholder.typicode.com是面向开发者的公开测试API,默认配置了允许所有域名跨域请求的CORS头,因此客户端的fetch能正常拿到响应并输出内容。
3. 关于res.text()和res.json()的说明
两者的写法差异并非问题核心,只是jsonplaceholder返回的是JSON格式数据,example.com返回的是HTML格式数据。即使改用res.text()请求jsonplaceholder,客户端依然能正常输出内容。
解决方向
- 要求目标服务器(如
example.com)配置允许当前客户端域名的CORS响应头; - 在服务器端搭建请求代理:让服务器代为请求
example.com,再将响应返回给客户端,绕过浏览器的跨域限制。
内容的提问来源于stack exchange,提问作者Ooker
相关产品推荐
相关产品推荐

