我的 React 应用程序中有一个 Person 组件,可以通过电子邮件地址从 API 端点获取详细的个人信息:
const Person = ({ email }) => {
const [userProfile, setUserProfile] = useState();
const { callApi } = useUtils();
const getUser = async ({ email }) => {
let profile = localStorage.getItem("Person:" + email)
if (!profile) {
const response = await callApi({
endpoint: `WebPage/GetUserProfile?Email=${email}`,
method: "GET"
});
setUserProfile(response);
localStorage.setItem("Person:" + email, JSON.stringify(response))
}
else {
setUserProfile(JSON.parse(profile))
}
}
useEffect(() => {
getUser({ email: email });
}, [])
return (
!userProfile ? (
<span>{email}</span>
) : (
<span title={userProfile.Email}>{userProfile.Name}</span>
)
)
}
export default Person;
它在我的网络应用程序中的很多地方使用,它们都很好,但现在我想在表中使用它来将电子邮件地址数据转换为详细的人员配置文件,因此我在每一行中插入此人员组件。 这是我的桌子:
<table>
<thead>
<tr>
<th>Title</th>
<th>Created By</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{currentItems.map(item => (
<tr key={item.ApprovalId}>
<td>{item.Title}</td>
<td><Person email={item.TicketCreatedByEmail} /></td>
<td>
<Button
variant="contained"
onClick={() => viewDetail(item.SignTicketId, item.ApprovalId)}
>Open</Button>
</td>
</tr>
))}
</tbody>
</table>
现在的问题是每次加载该表时,它都会向我的 API 的每一行发出获取请求,尽管不同行中有同一个人。例如,我从数据源中有这个表:
| Title | Created By | Action |
|---------------|---------------------------|-----------|
| test1 | [email protected] | |
| test2 | [email protected] | |
| test3 | [email protected] | |
| test4 | [email protected] | |
| test5 | [email protected] | |
| test6 | [email protected] | |
这张桌子上只有 2 个人,Alice 和 Bob。 理想情况下,应该只有 2 个请求发送到后端 API,并使用本地存储中的缓存结果来处理其余行。 但真正发生的是对所有行的 6 个请求,并请求重复的数据。 我想知道是否有查询或类似的方法来提高这种情况下的性能? 谢谢。
理想情况下,您应该创建一个 API 端点,该端点可以解析任何
currentItems
集合的所有用户配置文件数据。
但是在不改变后端任何内容的情况下,您所能期望的最好的结果就是用尽可能少的请求预先填充
currentItems
的配置文件。
例如,创建函数来获取项目并使用个人资料数据填充它们
// These are best defined in their own module, outside your components
const getUser = async (email) => {
let profile = JSON.parse(localStorage.getItem(`Person:${email}`));
if (!profile) {
profile = await callApi({
endpoint: `WebPage/GetUserProfile?Email=${encodeURIComponent(email)}`,
method: 'GET',
});
localStorage.setItem(`Person:${email}`, JSON.stringify(response));
}
return profile;
};
const getItemsAndProfiles = async () => {
const items = await getItems(); // assuming you already have something like this
// get unique emails
const emails = new Set(items.map((item) => item.TicketCreatedByEmail));
// create a map of email to profile
const profiles = Object.fromEntries(
await Promise.all(
Array.from(emails, async (email) => [email, await getUser(email)]),
),
);
// return items pre-populated with profile data
return items.map((item) => ({
...item,
UserProfile: profiles[item.TicketCreatedByEmail],
}));
};
然后在您的组件中,使用它来加载
currentItems
并将每个 item.UserProfile
传递给您的 <Person>
组件。
const [currentItems, setCurrentItems] = useState([]);
useEffect(() => {
getItemsAndProfiles().then(setCurrentItems).catch(console.error);
}, []);
// ...
<tbody>
{currentItems.map(item => (
<tr key={item.ApprovalId}>
<td>{item.Title}</td>
<td>
<Person
email={item.TicketCreatedByEmail}
profile={item.UserProfile}
/>
</td>
<td>
<Button
variant="contained"
onClick={() => viewDetail(item.SignTicketId, item.ApprovalId)}
>Open</Button>
</td>
</tr>
))}
</tbody>