web-dev-qa-db-fra.com

Faites défiler vers le haut de la page après le rendu dans react.js

J'ai un problème que je n'ai pas d'idées, comment résoudre . Dans mon composant de réaction, j'affiche une longue liste de données et quelques liens en bas . Après avoir cliqué sur l'un de ces liens, je remplis le liste avec nouvelle collection de liens et besoin de faire défiler vers le haut.

Le problème est - comment faire défiler vers le haut après nouvelle collection est rendue?

'use strict';

// url of this component is #/:checklistId/:sectionId

var React = require('react'),
  Router = require('react-router'),
  sectionStore = require('./../stores/checklist-section-store');


function updateStateFromProps() {
  var self = this;
  sectionStore.getChecklistSectionContent({
    checklistId: this.getParams().checklistId,
    sectionId: this.getParams().sectionId
  }).then(function (section) {
    self.setState({
      section,
      componentReady: true
    });
  });

    this.setState({componentReady: false});
 }

var Checklist = React.createClass({
  mixins: [Router.State],

  componentWillMount: function () {
    updateStateFromProps.call(this);
  },

  componentWillReceiveProps(){
    updateStateFromProps.call(this);
   },

render: function () {
  if (this.state.componentReady) {
    return(
      <section className='checklist-section'>
        <header className='section-header'>{ this.state.section.name }   </header>
        <Steps steps={ this.state.section.steps }/>
        <a href=`#/${this.getParams().checklistId}/${this.state.section.nextSection.Id}`>
          Next Section
        </a>
      </section>
    );
    } else {...}
  }
});

module.exports = Checklist;
84
Andrew Kovalenko

La solution originale ayant été fournie pour la toute première version de react , voici une mise à jour:

constructor(props) {
    super(props)
    this.myRef = React.createRef()   // Create a ref object 
}

componentDidMount() {
  this.myRef.current.scrollTo(0, 0);
}

render() {
    return <div ref={this.myRef}></div> 
}   // attach the ref property to a dom element
43
Andrew Kovalenko

Enfin .. j'ai utilisé:

componentDidMount() {
  window.scrollTo(0, 0)
}
164
lxm7

Vous pouvez utiliser quelque chose comme ça. ReactDom est pour react.14. Réagissez autrement.

    componentDidUpdate = () => { ReactDom.findDOMNode(this).scrollIntoView(); }
33
J. Mark Stevens

Cela pourrait, et devrait probablement, être traité avec refs :

"... vous pouvez utiliser ReactDOM.findDOMNode en tant que" hachure d'échappement ", mais nous le déconseillons, car il casse l'encapsulation et dans presque tous les cas, il existe un moyen plus clair de structurer votre code dans le modèle React.

Exemple de code:

class MyComponent extends React.Component {
    componentDidMount() {
        this._div.scrollTop = 0
    }

    render() {
        return <div ref={(ref) => this._div = ref} />
    }
}
12
GGAlanSmithee

Vous pouvez faire cela dans le routeur comme ça: 

ReactDOM.render((
<Router onUpdate={() => window.scrollTo(0, 0)} history={browserHistory}>
     <Route path='/' component={App}>
        <IndexRoute component={Home}></IndexRoute>
        <Route path="/about" component={About}/>
        <Route path="/work">
            <IndexRoute component={Work}></IndexRoute>
            <Route path=":id" component={ProjectFull}></Route>
        </Route>
        <Route path="/blog" component={Blog}/>
    </Route>
 </Router>
), document.getElementById('root'));

Le onUpdate={() => window.scrollTo(0, 0)} a mis le parchemin en haut . Pour plus d'informations, consultez: codepen link

8

Dans React Routing, le problème est que si nous redirigeons vers le nouvel itinéraire, cela ne vous mènera pas automatiquement en haut de la page.

Même moi, j'ai eu le même problème.

Je viens d'ajouter la ligne simple à mon composant et cela a fonctionné comme du beurre. 

componentDidMount() {
    window.scrollTo(0, 0);
}

Référez-vous: réagissez à la formation

7
Vishal Shetty

J'utilise react-router ScrollToTop Component dont le code est décrit dans la documentation de react-router

https://reacttraining.com/react-router/web/guides/scroll-restoration/scroll-to-top

Je change de code dans un seul fichier Routes et ensuite, plus besoin de changer le code dans chaque composant.

Exemple de code - 

Étape 1 - créer un composant ScrollToTop.js

import React, { Component } from 'react';
import { withRouter } from 'react-router';

class ScrollToTop extends Component {
  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      window.scrollTo(0, 0)
    }
  }

  render() {
    return this.props.children
  }
}

export default withRouter(ScrollToTop)

Étape 2 - Dans le fichier App.js, ajoutez le composant ScrollToTop après <Router

const App = () => (
  <Router>
    <ScrollToTop>
      <App/>
    </ScrollToTop>
  </Router>
)
6
Arpit

Voici une autre approche qui vous permet de choisir les composants montés sur lesquels vous souhaitez réinitialiser la position de défilement de la fenêtre sans dupliquer en masse ComponentDidUpdate/ComponentDidMount. 

L'exemple ci-dessous englobe le composant Blog avec ScrollIntoView (). Ainsi, si la route change lorsque le composant Blog est monté, ComponentDidUpdate du HOC mettra à jour la position de défilement de la fenêtre.

Vous pouvez tout aussi facilement l'envelopper sur l'ensemble de l'application, de sorte que tout changement d'itinéraire entraîne une réinitialisation de la fenêtre.

ScrollIntoView.js

import React, { Component } from 'react';
import { withRouter } from 'react-router';

export default WrappedComponent => {
  class ResetWindowScroll extends Component {
    componentDidUpdate = (prevProps) => {
      if(this.props.location !== prevProps.location) window.scrollTo(0,0);
    }

    render = () => <WrappedComponent {...this.props} />
  }
  return withRouter(ResetWindowScroll);
}

Routes.js

import React from 'react';
import { Route, IndexRoute } from 'react-router';

import App from '../components/App';
import About from '../components/pages/About';
import Blog from '../components/pages/Blog'
import Index from '../components/Landing';
import NotFound from '../components/navigation/NotFound';
import ScrollIntoView from '../components/navigation/ScrollIntoView';

 export default (
    <Route path="/" component={App}>
        <IndexRoute component={Index} />
        <Route path="/about" component={About} /> 
        <Route path="/blog" component={ScrollIntoView(Blog)} />
        <Route path="*" component={NotFound} />
    </Route>
);

L'exemple ci-dessus fonctionne très bien, mais si vous avez migré vers react-router-dom, vous pouvez le simplifier en créant un accessoire de rendu qui enveloppe le composant. 

Encore une fois, vous pouvez également le recouvrir tout aussi facilement sur vos routes (il suffit de changer la méthode componentDidMount en le code exemple de la méthode componentDidUpdate écrit ci-dessus, ainsi que de recouvrir ScrollIntoView avec withRouter).

Exemple de travail: https://codesandbox.io/s/qq4x5x43k9 (cliquer seulement sur home pour mettre à jour la position de la fenêtre)

conteneurs/ScrollIntoView.js

import { PureComponent, Fragment } from "react";

class ScrollIntoView extends PureComponent {
  componentDidMount = () => window.scrollTo(0, 0);

  render = () => this.props.children
}

export default ScrollIntoView;

components/Home.js

import React from "react";
import ScrollIntoView from "../containers/ScrollIntoView";

export default () => (
  <ScrollIntoView>
    <div className="container">
      <p>
        Sample Text
      </p>
    </div>
  </ScrollIntoView>
);
5
Matt Carlotta

C'est la seule chose qui a fonctionné pour moi (avec un composant de classe ES6):

componentDidMount() {
  ReactDOM.findDOMNode(this).scrollIntoView();
}
4
danharsanyi

Pour ceux qui utilisent des hooks, le code suivant fonctionnera.

React.useEffect(() => {
  window.scrollTo(0, 0);
}, []);

Notez que vous pouvez également importer directement useEffect: import { useEffect } from 'react'

2
Powderham

Si vous faites cela pour mobile, au moins avec chrome, vous verrez une barre blanche en bas.

Cela se produit lorsque la barre d'URL disparaît. Solution:

Modifiez le css pour height/min-height: 100% en height/min-height: 100vh.

Google Developer Docs

1
Artur Carvalho

Aucune des réponses ci-dessus ne fonctionne actuellement pour moi. Il s'avère que .scrollTo n'est pas aussi largement compatible que .scrollIntoView.

Dans notre App.js, dans componentWillMount() nous avons ajouté

this.props.history.listen((location, action) => {
        setTimeout(() => { document.getElementById('root').scrollIntoView({ behavior: "smooth" }) }, 777)
    })

C’est la seule solution qui fonctionne universellement pour nous. root est l'ID de notre application. Le comportement "lisse" ne fonctionne pas sur tous les navigateurs/appareils. Le délai d'attente de 777 est un peu prudent, mais nous chargeons beaucoup de données sur chaque page, nous avons donc dû procéder à des tests. Un 237 plus court pourrait fonctionner pour la plupart des applications.

1
Todd

Tout ce qui précède n'a pas fonctionné pour moi - je ne sais pas pourquoi mais: 

componentDidMount(){
    document.getElementById('HEADER').scrollIntoView();
}

travaillé, où HEADER est l'identifiant de mon en-tête

1
James Shiztar

Aucune des réponses ci-dessus ne fonctionne actuellement pour moi. Il s'avère que .scrollTo n'est pas aussi largement compatible que .scrollIntoView.

Dans notre App.js, dans componentWillMount() nous avons ajouté

    this.props.history.listen((location, action) => {
            setTimeout(() => { document.getElementById('root').scrollIntoView({ behavior: "smooth" }) }, 777)
        })

C’est la seule solution qui fonctionne universellement pour nous. root est l'ID de notre application. Le comportement "lisse" ne fonctionne pas sur tous les navigateurs/appareils. Le délai d'attente de 777 est un peu prudent, mais nous chargeons beaucoup de données sur chaque page, nous avons donc effectué des tests. Un 237 plus court pourrait fonctionner pour la plupart des applications.

0
Todd

Ce code provoquera un comportement fluide sur le scroll:

<div onClick={() => {
   ReactDOM.findDOMNode(this.headerRef)
      .scrollIntoView({behavior: "smooth"});
                }} 
  className='go-up-button' >
</div>

Vous pouvez transmettre d'autres paramètres à l'intérieur de scrollIntoView () La syntaxe suivante peut être utilisée:

element.scrollIntoView();
element.scrollIntoView(alignToTop); // Boolean parameter
element.scrollIntoView(scrollIntoViewOptions); // Object parameter

alignToTop Facultatif Est une valeur booléenne:

If true, the top of the element will be aligned to the top of the visible area of the scrollable ancestor. Corresponds to scrollIntoViewOptions: {block: "start", inline: "nearest"}. This is the default value.
If false, the bottom of the element will be aligned to the bottom of the visible area of the scrollable ancestor. Corresponds to scrollIntoViewOptions: {block: "end", inline: "nearest"}.

(scrollIntoViewOptions) Facultatif Est un objet avec les propriétés suivantes:

*behavior* Optional
    Defines the transition animation.
    One of "auto", "instant", or "smooth". Defaults to "auto".
*block* Optional
    One of "start", "center", "end", or "nearest". Defaults to "center".
*inline* Optional
    One of "start", "center", "end", or "nearest". Defaults to "nearest".

Plus de détails peuvent être trouvés ici: Documents MDN

0
Abhay Shiro

Toutes les solutions parlent d'ajouter le parchemin sur componentDidMount ou componentDidUpdate mais avec le DOM.

J'ai fait tout ça et je n'ai pas travaillé.

Alors, j'ai trouvé une autre solution qui me convient parfaitement.

Ajoutée componentDidUpdate() { window.scrollTo(0, 0) } sur l'en-tête, cette mine est hors de l'élément <Switch></Switch>. Juste gratuit dans l'application. Travaux.

J'ai aussi trouvé quelque chose de ScrollRestoration , mais je suis paresseux maintenant. Et pour l’instant, je garderai la méthode "DidUpdate".

J'espère que ça aide!

fais attention

0
Buzzcut Season

Quelque chose comme ça a fonctionné pour moi sur un composant:

<div ref="scroller" style={{height: 500, overflowX: "hidden", overflowY: "auto"}}>
      //Content Here
</div>

Ensuite, quelle que soit la fonction traitant des mises à jour:

this.refs.scroller.scrollTop=0
0
kojow7