#reactjs #react-hooks #use-effect #react-state-management
Вопрос:
Поэтому я работаю над веб-сайтом, который имеет бесконечную прокрутку и сортировку/фильтрацию. Проблема в том, что при изменении sortBy
метода мне нужно сбросить смещение для разбиения на страницы с бесконечной прокруткой.
Вот код для компонента:
function Listings({ setListingCount, sortBy }) {
const [listings, setListings] = useState([]);
const [isInitialLoading, setIsInitialLoading] = useState(true);
const [isLoading, setIsLoading] = useState(true);
const [apiError, setApiError] = useState(false);
const [offset, setOffset] = useState(0);
const [hasMore, setHasMore] = useState(true);
const limit = 12;
const observer = useRef();
const lastListingElementRef = useCallback((node) => {
if (isLoading) {
return;
}
if (observer.current) {
observer.current.disconnect();
}
observer.current = new IntersectionObserver((entries) =>
{
if (entries[0].isIntersecting amp;amp; hasMore) {
setOffset((prevOffset) => prevOffset limit);
}
});
if (node) {
observer.current.observe(node);
}
}, [isLoading, hasMore]);
function resetListings() {
setListings([]);
setIsInitialLoading(true);
setApiError(false);
setOffset(0);
setHasMore(true);
setListingCount('0');
}
useEffect(() => {
resetListings();
}, [sortBy]);
useEffect(async () => {
try {
setIsLoading(true);
const response = await axios.get(
'listings',
{
params: {
offset,
limit,
sb: sortBy
}
}
);
setListings((prevListingIds) => [
...new Set(
[...prevListingIds, ...response.data.rows]
)
]);
setListingCount(response.data.count);
setHasMore(response.data.rows.length > 0);
setIsLoading(false);
setIsInitialLoading(false);
} catch (error) {
setApiError(true);
setIsLoading(false);
setIsInitialLoading(false);
}
}, [sortBy, offset]);
return();
}
Первый useEffect
используется для сброса состояний в случае sortBy
изменений. Второй useEffect
используется для загрузки большего количества данных всякий раз, когда изменяется смещение или если sortBy
изменения. В настоящее время происходит то, что пользователь изменяет sortBy
значение, когда смещение не равно 0 (скажем, 12), затем второй useEffect
делает запрос get offset = 12
, прежде чем первый useEffect
сможет сбросить смещение обратно до 0. Но как только смещение сбрасывается на 0 первым useEffect
, выполняется другой запрос get offset = 0
, так что теперь он отображает 24 списка вместо 12, и это в неправильном порядке.
Как я должен иметь дело с useEffect
s, которые не гарантированно будут выполняться в том порядке, в котором я этого ожидаю? Есть ли другой способ реализовать эту логику? Спасибо вам за любую помощь, которая может быть оказана!
Комментарии:
1. Я немного сбит с толку, но пытаюсь понять. Порядок вызовов useEffect() зависит от порядка их срабатывания. Я бы присмотрелся к этому повнимательнее. Кроме того, асинхронность может вас испортить. Глядя на управление состоянием, которое у вас здесь есть, я бы предложил вам установить логическое значение состояния или что-нибудь дополнительное. Тогда вы можете использовать это в своем эффекте использования. Допустим, вы назвали это [needsUpdate, setNeedsUpdate]. В конце эффекта использования вы можете изменить состояние обновления потребностей и запустить другой эффект использования.
2. Таким образом, изменение значений не вызывает эффекта использования, а вызывает изменение нового значения. Кроме того, setState запустит повторный запрос для вас на затронутых компонентах.
3. @sloont Привет, спасибо за ваш ответ! Поэтому я пытаюсь сделать это прямо сейчас, но у меня возникла проблема, потому что мне нужен второй эффект использования, который будет выполняться либо при изменении смещения, либо при изменении сортировки. Но смещение также должно быть сброшено до 0 при изменении сортировки. Поэтому, если я установлю
needsUpdate
значениеtrue
в конце первого эффекта использования, второй эффект использования все равно будет срабатывать дважды: один раз, когдаoffset
установлено значение 0, и один раз, когдаneedsUpdate
установлено значение true. Это связано с тем, что я меняю переменные зависимости для второго эффекта использования на[needsUpdate, offset]
. Надеюсь, в этом есть смысл4. Я не совсем уверен, что это лучший способ сделать это. Потенциально вы могли бы превратить разделы функций в обещания, а затем пообещать. все это значит, что вы ждете окончания каждого процесса, прежде чем продвигаться вперед.