значения useState не те, которые я ожидаю в пользовательском хуке React для прокрутки - PullRequest
0 голосов
/ 10 апреля 2020

Я использую 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():

enter image description here

Приведенный выше журнал выглядит правильно. Я вижу, что значение scrollY меняется при прокрутке, я точно обновляю значение состояния, и все цифры соответствуют ожиданиям. Теперь возникает проблема (хотя я подозреваю, что проблема уже есть ... просто еще не раскрыта в этом журнале). Если я затем просто go вперед и назад с помощью элементов управления браузера (просто нажмите вперед и назад) и ничего не меняя, я вижу изменение журнала следующим образом:

enter image description here

Обратите внимание, что значение quote6 неожиданно стало равным 130. Ничего не изменилось, кроме того, что я нажал кнопку перемотки браузера. Я не прокручивал, не двигал мышь и не делал ничего подобного.

Очевидно, я не понимаю, когда и как эти значения создаются и сохраняются. Кто-нибудь может предложить что-нибудь? Это сводит меня с ума и отнимает слишком много времени (не говоря уже о том, что мой синдром самозванца немного разгорается, смеется).

Дополнительная информация: моим вдохновением для этого была необходимость сохранить такую ​​прокрутку в сочетании с этим твитом Райана Флоренса: https://twitter.com/ryanflorence/status/1029121580855488512?lang=en

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...