В приложении с реакцией, редуксом и редуксом, где лучше всего разместить код, который инициирует выборку данных, особенно в компоненте, включающем подкачку страниц (и где эти данные для текущей страницы кэшируются в хранить и загружать только в том случае, если он еще не кэширован)?
Я вижу из этого вопроса , что одно из предложений - сделать это в самом компоненте (например, в componentDidMount
), что я и сделал (за исключением того, что использовал функциональный компонент вместо этого используется хук useEffect
), но логика теперь распределена по нескольким местам и не выглядит чистой.
Скажем, пользователь щелкает по какой-то ссылке, которая их куда-то ведет (например, с помощьюact-router), которая загружает компонент, показывающий список пользователей. Когда это происходит, мы хотим инициировать выборку пользователей и показать некоторый прогресс (например, вращение), пока данные не станут доступны. Мы также хотим, чтобы то же самое происходило, когда пользователь щелкает по элементам управления подкачкой, чтобы получить следующую страницу пользователей и т. Д.
Вот то, что у меня сейчас есть, что я не считаю правильным:
- Начальная популяция ...
-
Users
(функциональный) компонент загружается.
- Получает реквизиты для
page
(индекс текущей страницы) и users
(массив отображаемых пользователей: изначально ноль).
- Он использует хук
useEffect
для выполнения побочного эффекта инициации извлечения. то есть он отправляет действие USERS_FETCH_REQUESTED
.
- Это обрабатывается сагой, которая в конечном итоге ответит
USERS_FETCH_SUCCESS
или USERS_FETCH_ERROR
.
- Это приведет к повторной визуализации компонента, на этот раз с заполненным массивом
users
.
- Paging ...
- Компонент
Users
отображает элементы управления подкачкой (кнопки для перехода на следующую страницу, последнюю страницу и т. Д.).
- Эти кнопки вызывают функцию
setPage
, переданную в реквизит, для обработки изменения страницы.
- Отправляет действие
SET_PAGE
в магазин.
- Затем редуктор изменяет значение
page
в состоянии приложения.
- Это вызывает повторную визуализацию компонента
Users
.
- При повторном рендеринге, поскольку при этом используется хук
useEffect
, и в качестве зависимости он имеет page
, запрос на извлечение будет запущен, как и раньше.
Все вышеперечисленное работает, но может показаться немного грязным, потому что компонент пользовательского интерфейса отвечает за получение данных. Кроме того, тот факт, что при вызове действия 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}/>))