
本文详解如何正确使用 React 的 useState 和 useEffect 实现基于异步 API 数据的下拉菜单渲染,避免常见陷阱如变量赋值不触发重绘、无限重渲染等问题。
本文详解如何正确使用 react 的 `usestate` 和 `useeffect` 实现基于异步 api 数据的下拉菜单渲染,避免常见陷阱如变量赋值不触发重绘、无限重渲染等问题。
在 React 中,直接修改普通变量(如 let contactDropdown = >)不会触发组件重渲染——这是初学者最常忽略的核心机制。React 只响应 状态(state)的变化,而非普通变量的重新赋值。因此,即使你成功从 Microsoft Graph API 获取了联系人数据,并构造了 元素,若未通过 useState + setState 更新状态,UI 将始终保持初始空内容 >。
✅ 正确做法:用 useState 管理数据,用 useEffect 控制副作用
首先,将联系人数据本身存入状态(推荐方式),而非预渲染的 JSX:
import { useState, useEffect } from 'react';
const App = () => {
const [contacts, setContacts] = useState([]); // ✅ 存储原始数据,非 JSX
useEffect(() => {
const fetchContacts = async () => {
try {
await Office.onReady();
// 获取 Microsoft Graph 访问令牌
const graphTokenResponse = await graphAuth.getToken(graphLoginRequest);
const accessToken = graphTokenResponse.accessToken;
// 获取当前邮件信息
const message = await getMessage(
accessToken,
Office.context.mailbox.item.itemId
);
// 调用自定义后端接口获取联系人
const contactsData = await getContactsByEmail(
message.from.emailAddress.address
);
// ✅ 更新状态 → 触发重渲染
setContacts(contactsData);
} catch (error) {
console.error('Failed to load contacts:', error);
}
};
fetchContacts();
}, []); // ? 空依赖数组:仅在组件挂载时执行一次
// ✅ 渲染逻辑放在 return 中,基于最新 state
return (
<div>
{contacts.length > 0 ? (
<select aria-label="Select a contact">
{contacts.map((contact) => (
<option key="{contact.id}" value="{contact.id}">
{contact.name}
</option>
))}
</select>
) : (
<p>Loading contacts or no results found.</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill10835" title="React 组件生成器"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20dee630206.jpg" alt="React 组件生成器" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill10835" title="React 组件生成器" class="overflowclass">React 组件生成器</a>
<p class="overflowclass">根据项目规范生成 React 和 Vue 组件,包括 TypeScript 类型定义、Ant Design 5 集成、Tailwind CSS 样式及 Vitest 测试文件。当用户提出创建、生成或搭建前端组件的需求时启用,例如:“帮我写一个表格组件”、“生成一个弹窗”、“create a form component”、“写一个列表页”、“生成一个下拉选择器”。该能力在以下任一场景触发:涉及 React/TSX/Vue 组件生成、UI 组件创建,或为组件生成测试文件。</p>
</div>
<a rel="nofollow" href="/xiazai/skill10835" title="React 组件生成器" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
)}
</div>
);
};
export default App;
⚠️ 关键注意事项
-
不要在组件顶层直接执行异步操作:否则每次渲染都会重复调用 API,极易导致无限循环(尤其当
setState触发重渲染时); -
避免将 JSX 存入 state:虽然
useState()在技术上可行,但不利于后续扩展(如添加搜索、分页、联动逻辑等),且违背“状态即数据”的设计原则; -
务必处理加载与错误状态:实际项目中应加入
loading和error状态,提升用户体验; -
确保
key唯一且稳定:contact.id是理想选择;若无 ID,避免使用index(可能导致 DOM 复用异常); -
Office.js 上下文需在
Office.onReady()后使用:本例已正确包裹,确保 Outlook 加载完成后再访问邮箱项。
✅ 总结
要让下拉框随 API 数据动态呈现,只需三步:
- 用
useState初始化联系人数据(如[]); - 用
useEffect(..., [])封装异步获取逻辑,确保只执行一次; - 在 JSX 中基于
contacts数组条件渲染—— React 会自动响应状态更新并刷新 UI。
这才是符合 React 数据流规范、可维护、可扩展的标准实践。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










