【发布时间】:2023-11-10 20:54:01
【问题描述】:
在带有 react、redux 和 redux saga 的应用中,哪里是放置启动数据获取的代码的最佳位置,尤其是在包含分页的组件中(并且当前页面的数据缓存在存储并且仅在尚未缓存时才应获取)?
我可以从this question 看到一个建议是在组件本身中执行此操作(例如在componentDidMount 中),这就是我所做的(除了我使用了使用useEffect 的功能组件钩子代替),但逻辑现在分布在几个地方,看起来并不干净。
假设用户单击某个链接将他们带到某个地方(例如使用 react-router),该链接加载了一个显示用户列表的组件。发生这种情况时,我们希望启动用户获取,并显示一些进度(例如微调器),直到数据可用。当用户单击分页控件以获取下一页用户等时,我们也希望发生同样的事情。
这是我目前拥有的,我认为不太正确:
- 初始人口...
-
Users(功能性)组件加载。 - 这会接收
page(当前页面的索引)和users(要显示的用户数组:最初为 null)的 props。 - 它使用
useEffect挂钩来执行启动提取的副作用。即它发送一个USERS_FETCH_REQUESTED动作。 - 这是由 saga 处理的,最终会以
USERS_FETCH_SUCCESS或USERS_FETCH_ERROR响应。 - 这将导致组件被重新渲染,这次填充了
users数组。
-
- 分页...
-
Users组件呈现分页控件(用于转到下一页、最后一页等的按钮)。 - 这些按钮调用传递给 props 的
setPage函数,以处理页面更改。 - 这会将
SET_PAGE操作分派到商店。 - reducer 然后更改应用程序状态下的
page值。 - 这会导致
Users组件的重新渲染。 - 重新渲染时,因为它使用
useEffect钩子,并且它具有page作为依赖项,所以它将像以前一样启动获取请求。
-
以上所有方法都有效,但可能看起来有点混乱,因为 UI 组件负责导致数据获取发生。此外,调用setPage 操作在其中没有任何内容可以启动用户获取,但在逻辑上可能应该这样做。但是,如果我们确实将这个逻辑放在那个动作中,那么当这个不是由页面更改引起的时候,我们如何让初始加载发生。
需要注意的重要一点是,我们并不总是想在组件加载时获取数据:我们只想在应用程序在商店中的状态还没有的情况下这样做包含当前页面的用户。例如如果加载了用户的第 1 页,则用户导航到应用程序中的其他位置,然后返回到该组件:该组件应该只显示已缓存在商店中的用户。
以下是当前方法下代码的大致样子:
const Users: React.FC<{
page: number,
users: User[] | null,
isFetching: boolean,
fetchError?: Error,
setPage: (page: number) => void,
fetchUsers: (page: number) => void
}> = ({page, users, isFetching, fetchError, setPage, fetchUsers}): JSX.Element => {
useEffect(() => {
// Fetch users if we don't already have them in the props.
!users && fetchUsers(page)
}, [users, page, fetchUsers])
return (
<div>
<button id="previousPageButton" onClick={() => setPage(page - 1)}><</button>
<button id="nextPageButton" onClick={() => setPage(page + 1)}>></button>
{fetchError
? <div>Error fetching users: {fetchError.message}</div>
: (isFetching || !users
? <div>Fetching...</div>
: users.map(user => <UserRow user={user} key={user.id}/>))
【问题讨论】:
标签: reactjs redux react-redux redux-saga