Como implementar a restauração de rolagem para o React Router SPA

11

Estou criando um aplicativo de página única do React e notei que a restauração de rolagem não parece funcionar conforme o esperado no Chrome (e talvez em outros navegadores).

No repositório do github react-router-dom, eles têm uma página que diz que os navegadores estão começando a manipular nativamente a rolagem para aplicativos de página única, e o comportamento seria semelhante ao de uma página da web tradicional que não seja SPA, se history.scrollRestorationestiver definida como auto.

O comportamento que preciso é indicado nessa página:

  1. Rolar para cima na navegação para não iniciar uma nova tela rolada para baixo.
  2. Restaurando posições de rolagem da janela e elementos de estouro nos cliques "voltar" e "encaminhar" (mas não nos cliques no link!)

Mas também preciso desabilitar o comportamento para rotas que contenham guias ou um carrossel.

Aqui está um link para as especificações do Chrome sobre o assunto .

O que estou observando na versão 78.0.3904.97 do Chrome (versão oficial) (64 bits) para OS X, é o que parece ser o que eu esperaria da history.scrollRestoration manualconfiguração. Ou seja, quando eu sou rolado até a metade da página e clico em um link, a página seguinte é rolada até a metade da página, no mesmo ponto da página anterior.

Eu verifiquei o history.scrollRestorationem vários pontos e acho que ele começa e permanece auto, o padrão,

Um ponto importante aqui é a resposta do @ TrevorRobinson "as tentativas automáticas do navegador na restauração de rolagem ... ... geralmente não funcionam para aplicativos de página única ..." Ok ... Encontrei suporte consistente para history.scrollRestoration, mas aparentemente, os navegadores são péssimos ao fazer a restauração de rolagem. Então isso deve ser observado aqui , o que teria me poupado tempo hoje.

Então, procuro maneiras de fazer isso manualmente, e não estou claro o caminho a seguir. react-router-scrolldiz que não é compatível com o React Router v4, mas não menciona a v5, atual nesta pergunta. Então, devo assumir que v5 também não é compatível?

Então eu olho mais para um caminho a seguir, e acharam esta resposta SO sobre como lidar com rolagem restauração com Reagir Router v4 ... Devo assumir que vai trabalhar com Reagir Router v5? Atualização: parece não funcionar para mim na v5. Eu tentei várias configurações. Também não consegui fazê-lo funcionar completamente com o React Router v4. Eu sabia que ele ganhou vida, pelo menos, pois rolava para o topo de uma nova página, mas a restauração na história não ocorre.

Também obtive a função react-router-scroll-memory , mas ele não tem opções para desativar a rolagem em rotas designadas, como o que seria necessário para guias ou um carrossel ... Eu poderia simplesmente hacká-lo para fazê-lo funcionar.

Eu considerei usar oaf-react-router , mas ele não diz nada na documentação sobre como desativar a restauração de rolagem ou a rolagem para cima em determinadas rotas. Edit: Ele realmente lida com isso, conforme descrito na minha resposta.

Existe algo que eu tenha esquecido? Qual é o padrão para lidar com esse problema, porque não posso ser o único que precisa desse recurso. Parece que estou fazendo algo ousado e experimental, mas só preciso que meu site role como um site normal.

BBaysinger
fonte
2
Você deve dar uma olhada no Nextjs , eles implementaram isso através do cache do histórico.
Jurrian
Legal! Vou dar uma olhada mais de perto quando puder sair deste projeto.
BBaysinger 15/11/19

Respostas:

4

Uma maneira de fazer isso é com oaf-react-router . Use as shouldHandleActionopções nas configurações. A função é aprovada previousLocatione nextLocationpode ser usada para determinar se a rolagem deve ser redefinida / restaurada e, falsese não for , retornará .

const history = createBrowserHistory();

const settings = {
   shouldHandleAction: (previousLocation, nextLocation) => {
       // Inspect/compare nextLocation and/or previousLocation.
       return false // false if you don't want scroll restoration.
   }
};

wrapHistory(history, settings);

oaf-react-router funciona com o React Router v4 e v5 e lida com a acessibilidade, onde muitos roteadores SPA não, por isso pode ser a solução mais completa no momento.

Curiosamente, a documentação não detalha esse recurso.

Se alguém tiver uma solução que funcione e seria considerada mais padrão, forneça uma resposta aqui e considerarei alterar a resposta selecionada.

BBaysinger
fonte