Далее, про скролл.
В принципе для SPA-приложений это база, если при переходах на разные страницы мы не хотим оставаться в одной позиции скролла, нам нужно самостоятельно скроллить вверх страницы.
Кажется есть функционал во всех роутерах и мета-фреймворках, и как отдельные либы.
В Tramvai был старый модуль, который умел вызвать scroll top или к якорю, с логикой что бы срабатывал строго один раз после перехода.
Из коробки проблема опять таки при браузерных back/forward, в этих случаях мы хотим восстановить позицию скролла, а не сбросить ее наверх.
И конечно кейсы с виртуальными списками / пагинацией, но это уже немного out of scope, кажется тут лучше якорей ничего нет.
Но мы словили ещё интересную проблему:
- у страницы очень тяжёлый рендер
- браузер детектит soft navigation до отрисовки и делает восстановление скролла
- наш автоскролл не попадает в этот paint и у пользователя скачет скролл на одном экране
Зеркальная проблема, если автоскролл сработал до отрисовки текущего экрана а браузер восстановил скролл после paint события, которое стриггерил реакт при рендере следующего экрана.
Я долго возился с отключением/включением браузерного механизма восстановления при разных условиях для разных записей в history, все стало работать на первый взгляд идеально, а потом я включил example с View Transitions...
Потратил ещё больше времени, но все время упираюсь в одну проблему - браузерное восстановление скролла и анимация не синхронизируются, попадают в разные paint, какие бы хаки я там не делал, включая оборачивание скролла в rAF.
Пришел к тому что единственный способ рабочий это:
- браузерный механизм отключить полностью
- сохранять позицию скролла для каждой записи в history вручную
- восстанавливать/сбрасывать ее тоже полностью вручную
Так как возможны переходы вида history.go(-2), в session storage для каждой навигации (по индексу) храню позицию скролла.
Отдельно пришлось повозиться, снова, с браузерными back/forward - о переходе узнаешь пост-фактум, history уже изменен, и как раз плюсом стало хранение позиции скролла в session storage.
Работает как часы, кастомизируется, но дебажить такое это конечно никакого удовольствия - https://github.com/tramvaijs/tramvai/blob/main/packages%2Fmodules%2Fautoscroll%2Fsrc%2Fcomponents%2FScrollRestoration.tsx
Post #239
549