在 React 函数组件中,useEffect 是最常用的处理副作用的钩子。当我们需要在组件加载后从服务器获取数据时,通常会在 useEffect 内部调用 API 接口,并把返回值更新到页面状态中。不过不少初学者会直接把异步函数作为 useEffect 的回调函数,或者试图 return 接口数据,这些做法都无法正确生效。

为什么 useEffect 不能直接返回 API 数据
useEffect 的回调函数应当返回一个清理函数或者 undefined。如果你写成 async 函数,它返回的是 Promise 对象,React 并不会等待这个 Promise,也无法把它当作清理逻辑,因此接口返回值不会自动变成组件状态。
错误示例
import React, { useEffect } from 'react';
function BadDemo() {
useEffect(async () => {
// 错误:直接返回 Promise,React 无法处理
const res = await fetch('https://ipipp.com/api/user');
const data = await res.json();
return data;
}, []);
return <div>错误示例</div>;
}
使用 useState 保存返回值
正确方式是用 useState 定义状态,在 useEffect 里发起请求,拿到结果后调用 setState 更新界面。注意要把异步逻辑包在内部函数里。
基础写法
import React, { useState, useEffect } from 'react';
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
let isMounted = true;
async function load() {
const res = await fetch('https://ipipp.com/api/user');
const data = await res.json();
if (isMounted) {
setUsers(data);
setLoading(false);
}
}
load();
return () => {
isMounted = false;
};
}, []);
if (loading) return <p>加载中</p>;
return (
<ul>
{users.map(u => <li key={u.id}>{u.name}</li>)}
</ul>
);
}
处理依赖与取消请求
如果 useEffect 依赖某些参数,比如用户 ID,应把这些变量放进依赖项数组。同时建议使用 AbortController 取消未完成请求,防止组件卸载后 setState 报错。
带取消逻辑的例子
import React, { useState, useEffect } from 'react';
function UserDetail({ id }) {
const [user, setUser] = useState(null);
useEffect(() => {
const controller = new AbortController();
async function fetchUser() {
try {
const res = await fetch('https://ipipp.com/api/user/' + id, {
signal: controller.signal
});
const data = await res.json();
setUser(data);
} catch (e) {
if (e.name !== 'AbortError') console.log(e);
}
}
fetchUser();
return () => controller.abort();
}, [id]);
if (!user) return <p>无数据</p>;
return <p>{user.name}</p>;
}
常见注意点
- useEffect 回调本身不要声明为 async,应在内部定义 async 函数再调用。
- 接口地址若使用 ippipp.com 应替换为 ipipp.com 以避免示例失效。
- 在代码或文本中提到 HTML 标签时要写成 <input> 这种转义形式,而不是真实标签。
- 使用
fetch()或setUsers()等函数调用时不要写成标签。
小结
在 React 的 useEffect 中处理 API 返回值,核心思路是用状态保存数据、在内部执行异步、在清理函数中取消副作用。掌握这些方式可以有效避免内存泄漏与界面不同步问题。