Comment implémenter la restauration de défilement pour React Router SPA


11

Je crée une application React à page unique et j'ai remarqué que la restauration du défilement ne semble pas fonctionner comme prévu dans Chrome (et peut-être dans d'autres navigateurs).

Sur le référentiel github de react-router-dom, ils ont une page qui dit que les navigateurs commencent à gérer nativement le défilement pour les applications d'une seule page, et le comportement serait similaire à celui d'une page Web non SPA traditionnelle, si history.scrollRestorationest défini sur auto.

Le comportement dont j'ai besoin est indiqué sur cette page:

  1. Défilement vers le haut sur la navigation pour ne pas démarrer un nouvel écran défilé vers le bas.
  2. Restauration des positions de défilement de la fenêtre et des éléments de débordement lors des clics "arrière" et "avant" (mais pas les clics de lien!)

Mais je dois également désactiver le comportement pour les itinéraires qui contiennent des tabulations ou un carrousel.

Voici un lien vers les spécifications de Chrome sur le problème .

Ce que j'observe dans Chrome version 78.0.3904.97 (version officielle) (64 bits) pour OS X, est ce qui semble être ce que j'attendrais du history.scrollRestoration manualparamètre. Autrement dit, lorsque je défile à mi-chemin d'une page et que je clique sur un lien, la page suivante défile à mi-chemin de la page, au même point que la page précédente.

J'ai vérifié le history.scrollRestorationà différents points et je trouve qu'il démarre et reste auto, par défaut,

Un point important ici est celui de la réponse de @ TrevorRobinson "les tentatives automatiques de restauration du défilement du navigateur ... ... ne fonctionnent généralement pas pour les applications d'une seule page ..." Ok ... J'ai trouvé un support cohérent pour history.scrollRestoration, mais apparemment, les navigateurs sont fous de FAIRE la restauration de défilement. Ensuite, cela devrait être noté ici , ce qui m'aurait fait gagner du temps aujourd'hui.

Ensuite, je cherche des moyens de le faire manuellement, et je ne suis pas sûr de la voie à suivre. react-router-scrolldit qu'il n'est pas compatible avec React Router v4, mais ne mentionne pas la v5, qui est actuelle à cette question. Dois-je donc supposer que la v5 n'est pas non plus compatible?

Je cherche donc plus loin et j'ai trouvé cette réponse SO sur la façon de gérer la restauration du défilement avec React Router v4 ... Dois-je supposer que cela fonctionnera avec React Router v5? Mise à jour: il ne semble pas fonctionner pour moi dans la v5. J'ai essayé plusieurs configurations. Je ne pouvais pas non plus le faire fonctionner complètement avec React Router v4. Je savais qu'il était devenu vivant au moins, car il faisait défiler vers le haut sur une nouvelle page, mais la restauration dans l'histoire ne se produit pas.

J'ai également fait fonctionner react-router-scroll-memory , mais il n'a pas d'options pour désactiver le défilement sur les routes désignées, comme ce qui serait nécessaire pour les onglets ou un carrousel ... Je pourrais juste le pirater pour le faire fonctionner.

J'ai envisagé d'utiliser oaf-react-router , mais cela ne dit rien dans la documentation sur la désactivation de la restauration du défilement ou du défilement vers le haut pour certaines routes. Edit: Il gère réellement cela, comme indiqué dans ma réponse.

Y a-t-il quelque chose que j'ai oublié? Quelle est la norme pour traiter ce problème, car je ne peux pas être le seul à avoir besoin de cette fonctionnalité. On dirait que je fais quelque chose de nerveux et d'expérimental, mais j'ai juste besoin que mon site défile comme un site normal.


2
Vous devriez jeter un œil à Nextjs , ils l'ont implémenté en mettant en cache l'historique.
Jurrian

Cool! Je regarderai de plus près quand je pourrai descendre de ce projet.
BBaysinger

Réponses:


4

Une façon de le faire est d'utiliser oaf-react-router . Utilisez les shouldHandleActionoptions dans les paramètres. La fonction est passée previousLocationet nextLocationque vous pouvez utiliser pour déterminer si le défilement doit être réinitialisé / restauré, et retourner falsesinon.

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 fonctionne avec React Router v4 et v5, et gère l'accessibilité, là où de nombreux routeurs SPA ne le font pas, donc c'est peut-être la solution la plus complète pour le moment.

Curieusement, la documentation ne développe pas cette fonctionnalité.

Si quelqu'un d'autre a une solution qui fonctionne et qui serait considérée comme une norme, veuillez fournir une réponse ici, et j'envisagerai de changer la réponse sélectionnée.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.