组件挂载时获取数据
在 useEffect 中从 API 获取 JSON,将响应保存到状态中,并使用空依赖数组仅触发一次获取操作。
组件挂载时获取数据 是 CoddyKit 上的免费 Frontend Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Frontend Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Frontend Academy 课程共包含 4 节课。
数据获取模式
React 中标准的数据获取模式是:1)定义加载、错误和数据状态;2)在 useEffect 中使用空依赖数组 [] 获取数据;3)在回调中更新状态;4)根据状态进行渲染。
完整示例
这是一个完整示例:组件挂载时获取用户,并处理加载和错误状态。
interface User { id: number; name: string; email: string; }
function UserList() {
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetch('/api/users')
.then(res => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
})
.then(data => setUsers(data))
.catch(err => setError(err.message))
.finally(() => setLoading(false));
}, []);
if (loading) return <Spinner />;
if (error) return <ErrorMessage message={error} />;
return <ul>{users.map(u => <UserItem key={u.id} {...u} />)}</ul>;
}在 useEffect 中使用 async/await
useEffect 的回调不能直接使用 async(因为它会返回 Promise,而 React 会将其解释为清理函数)。相反,请定义一个内部的 async 函数并立即调用它。
useEffect(() => {
async function fetchUsers() {
try {
const res = await fetch('/api/users');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
setUsers(data);
} catch (err) {
setError((err as Error).message);
} finally {
setLoading(false);
}
}
fetchUsers();
}, []);检查响应状态
fetch 不会因 HTTP 错误(4xx、5xx)而抛出异常——它只会在网络失败时抛出异常。请始终检查 response.ok,并针对错误响应手动抛出异常。
const res = await fetch('/api/data');
if (!res.ok) {
// Could also use res.status for specific handling
throw new Error(`Server responded ${res.status}: ${res.statusText}`);
}
const data = await res.json();依赖项变化时获取数据
将依赖项(例如路由参数或属性中的 ID)添加到副作用的依赖数组中。每当依赖项发生变化时,副作用都会重新运行并获取最新数据。
const { userId } = useParams();
useEffect(() => {
if (!userId) return;
setLoading(true);
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(setUser)
.finally(() => setLoading(false));
}, [userId]);副作用中的 POST 请求
副作用也可以发送 POST、PUT、DELETE 请求,但这些请求通常由事件触发(表单提交、按钮点击),而不是由挂载时的副作用触发。请让副作用负责加载数据,并使用事件处理程序执行变更。
自定义 useFetch 钩子
将获取数据、加载和错误处理模式提取到自定义钩子中,以便在多个组件之间复用。
function useFetch<T>(url: string) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
setLoading(true);
fetch(url)
.then(r => { if (!r.ok) throw new Error(`${r.status}`); return r.json(); })
.then(setData)
.catch(e => setError(e.message))
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}安全解析 JSON
请始终将 res.json() 包裹在 try/catch 中——格式错误的 JSON 会抛出 SyntaxError。外层 catch 会处理它,但了解错误来源有助于调试。
API 基础 URL 配置
不要将 API URL 硬编码。请使用环境变量(import.meta.env.VITE_API_URL)配置基础 URL。创建一个集中管理的 api.ts 文件,并在其中配置 fetch 包装器。
const API_BASE = import.meta.env.VITE_API_URL;
async function apiFetch<T>(path: string): Promise<T> {
const res = await fetch(`${API_BASE}${path}`, {
headers: { 'Authorization': `Bearer ${getToken()}` }
});
if (!res.ok) throw new Error(`API error ${res.status}`);
return res.json();
}何时迁移到 React Query
手动获取数据的模式适用于简单场景。当您需要缓存、后台重新获取、分页或数据变更时,请迁移到 React Query(TanStack Query)——它可以可靠地处理所有这些模式。
显示加载骨架屏
不要使用旋转指示器,而应显示与已加载内容形状相匹配的骨架界面。这样可以缩短用户感知的加载时间,并防止布局偏移。
快速检查
为什么不能直接将 useEffect 的回调设为 async?
回顾:在 useEffect 中获取数据
定义加载、错误和数据状态。在 useEffect 中使用空依赖数组 [] 获取数据。定义内部 async 函数,不要将回调设为 async。始终检查 res.ok。动态获取数据时,将 URL 或 ID 添加到依赖项中。将逻辑提取到 useFetch 自定义钩子中以便复用。在生产环境中获取数据时,请考虑使用 TanStack Query。
常见问题解答
「组件挂载时获取数据」课时是免费的吗?
是的 — 「组件挂载时获取数据」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Frontend Academy 课程的其余内容,请升级到 CoddyKit PRO。 Frontend Academy 课程共包含 4 节课。
「组件挂载时获取数据」这节课中我会学到什么?
在 useEffect 中从 API 获取 JSON,将响应保存到状态中,并使用空依赖数组仅触发一次获取操作。 你通过在浏览器中直接运行的动手代码来练习 Frontend Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Frontend Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Frontend Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「组件挂载时获取数据」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Frontend Academy 课中编写并运行代码吗?
能。每节 Frontend Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。