Я использую React с @reach/router
и пытаюсь создать пользовательский хук, который сохранит позицию прокрутки для посещенных маршрутов при прокрутке до верхней части страницы для новых маршрутов. Что у меня вроде работает, но значения для каждого маршрута меняются таким образом, что для меня не имеет смысла (и портят местоположение).
Этот код:
import { useState, useLayoutEffect } from 'react';
import { WindowLocation } from '@reach/router';
interface ScrollPositions {
[key: string]: number;
}
export const useScrollPosition = (props: WindowLocation) => {
const [locations, setLocations] = useState<ScrollPositions>({});
const { pathname } = props;
let newVal: ScrollPositions;
const listener = () => {
newVal = { [pathname]: window.scrollY };
setLocations((prevState) => ({ ...prevState, ...newVal }));
};
useLayoutEffect(() => {
window.addEventListener('scroll', listener);
if (!locations[pathname]) {
window.scrollTo(0, 0);
} else {
window.scrollTo(0, locations[pathname]);
}
return () => {
window.removeEventListener('scroll', listener);
};
}, [pathname]);
};
Используется очень просто в каком-то компоненте, таком как
const location = useLocation();
useScrollPosition(location);
Что я хочу сделать, это проверить путь к местоположению (скажем, /quote/1
) и установить значение в состоянии, которое отслеживает значение для window.scrollY. Таким образом, обновляется при прокрутке с использованием добавляемого чётного кода.
Полученный объект состояния выглядит примерно так:
{/quote/1: 433, /quote/2: 76}
Учитывая это состояние, когда вы go возвращаетесь к /quote/1
вертикали позиция должна быть установлена с window.scrollTo(0, 433)
, и это, кажется, работает, первоначально. Однако, если вы go взад-вперед несколько раз, все начинает меняться. Вы получаете новые значения для бита window.scrollY, и они продолжают изменяться, когда вы go переходите между маршрутами назад и вперед, иногда принимая очень небольшое число, иногда назначая номер для предыдущего маршрута следующему маршруту.
Пример, вот журнал моих значений, когда свиток обновляет их. Я также регистрирую весь объект состояния на этом снимке экрана внутри useLayoutEffect()
:
Приведенный выше журнал выглядит правильно. Я вижу, что значение scrollY меняется при прокрутке, я точно обновляю значение состояния, и все цифры соответствуют ожиданиям. Теперь возникает проблема (хотя я подозреваю, что проблема уже есть ... просто еще не раскрыта в этом журнале). Если я затем просто go вперед и назад с помощью элементов управления браузера (просто нажмите вперед и назад) и ничего не меняя, я вижу изменение журнала следующим образом:
Обратите внимание, что значение quote6 неожиданно стало равным 130. Ничего не изменилось, кроме того, что я нажал кнопку перемотки браузера. Я не прокручивал, не двигал мышь и не делал ничего подобного.
Очевидно, я не понимаю, когда и как эти значения создаются и сохраняются. Кто-нибудь может предложить что-нибудь? Это сводит меня с ума и отнимает слишком много времени (не говоря уже о том, что мой синдром самозванца немного разгорается, смеется).
Дополнительная информация: моим вдохновением для этого была необходимость сохранить такую прокрутку в сочетании с этим твитом Райана Флоренса: https://twitter.com/ryanflorence/status/1029121580855488512?lang=en