Reakt.js'de oluşturduktan sonra sayfanın üstüne gidin


169

Hiçbir fikrim yok, nasıl çözeceğim bir problemim var. Tepki bileşenimde uzun bir veri listesi ve altta birkaç bağlantı görüntüler. Bu bağlantılardan herhangi birine tıkladıktan sonra listeyi yeni bağlantı koleksiyonuyla dolduruyorum ve yukarı kaydırmam gerekiyor.

Sorun şu ki - yeni koleksiyon oluşturulduktan sonra nasıl yukarı kaydırılır ?

'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;

Yanıtlar:


327

Sonunda .. kullandım:

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

DÜZENLEME: React v16.8 +

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

2
Bu benim için işe yarayan tek çözüm. Ayrıca denendi: ReactDOM.findDOMNode (this) .scrollTop = 0 ve componentDidMount () {this._div.scrollTop = 0} render () {dönüş <div ref = {(ref) => this._div = ref} />}
Michael Bushe

W3Schools'a göre, bu çözüm şu anda tüm tarayıcılar tarafından desteklenmektedir. Ayrıca ReactDOM kütüphanesi, React'in gelecekteki sürümlerinde kullanımdan kaldırılıyor.
BishopZ

2
@Tomasz - Yüksekliğe veya minimum yüksekliğe ayarlanmış bazı div'ler olduğunda bazen hala bu sorunları yaşadığımı fark ettim:% 100. Çıkarmak ya da bir ebeveynin içine sarmak ya da hala kayabileceği ağaca doğru ilerlemek zorunda kaldım
rasemik

2
Durum değişikliği sayfanın yeniden oluşturulmasına neden olduğunda CDM tetiklenemeyebileceğinden, bu benim için çalıştı ancak componentDidMount altında çalışmadı. Bu çağrıyı koyun - window.scrollTo (0, 0); - nerede olursanız olun, durumu değiştirirsiniz.
Puneet Lamba

4
Kanca kullananlar için aşağıdaki kod çalışacaktır. React.useEffect(() => { window.scrollTo(0, 0); }, []); Ayrıca, useEffect'i doğrudan da içe aktarabilirsiniz:import { useEffect } from 'react'
Powderham

72

Orijinal çözüm, reaksiyonun çok erken bir sürümü için sağlandığından , bir güncelleme:

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

this.getDOMNode === tanımsız
Dave Lunny

1
@DaveLunny reaktif15 olabilir? ReactDOM'u içe aktarmayı ve yapmayı deneyinReactDOM.findDOMNode(this).scrollTop = 0
Marcus Ericsson

12
this is undefined in arrow functionsyanlış. Bu anahtar kelime, developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Joe Delgado

Mümkünse ReactDom.findDOMNode () işlevinden kaçınmalısınız. Bunun yerine ref kullanın. Burada düzgün kaydırma kullanarak bir çözüm
bbrinx

default.a.createRef bir işlev değil
Anupam Maurya

48

Böyle bir şey kullanabilirsiniz. ReactDom reaksiyon içindir. Sadece başka türlü tepki ver.

    componentDidUpdate = () => { ReactDom.findDOMNode(this).scrollIntoView(); }

React 16+ için güncelleme 11/11/2019

  constructor(props) {
    super(props)
    this.childDiv = React.createRef()
  }

  componentDidMount = () => this.handleScroll()

  componentDidUpdate = () => this.handleScroll()

  handleScroll = () => {
    const { index, selected } = this.props
    if (index === selected) {
      setTimeout(() => {
        this.childDiv.current.scrollIntoView({ behavior: 'smooth' })
      }, 500)
    }
  }


Bu sayfadaki tüm önerilerden, benim için çalışan tek şey bu.
Josh F

Not: componentDidUpdate sizin için çalışmazsa componentDidMountbaşka bir alternatiftir.
Alex Fallenstedt

findDOMNode, temeldeki DOM düğümüne erişmek için kullanılan bir kaçış kapağıdır. Çoğu durumda, bu kaçış kapağının kullanılması önerilmez, çünkü bileşen soyutlamasını deler. StrictMode'da kullanımdan kaldırıldı. reatjs.org/docs/react-dom.html
Vivek Kumar

16

React Routing'de yeni rotaya yönlendirirsek, otomatik olarak sizi sayfanın üstüne götürmeyecek sorunu vardır.

Ben de aynı sorunu yaşadım.

Bileşene tek bir satır ekledim ve tereyağı gibi çalıştı.

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

Bakınız: tepki eğitimi


'üste atla' düğmem için bunu kullanırsam önerilen yol bu mu? veya pencere nesnesini kullanmadığımız bir 'tepki' yolu varsa?
Toxnyc

1
Bildirime katıldığınız için teşekkürler, verdiğim çözüm v5'ten daha düşük bir tepki yönlendirici dom sürümü için geçerlidir, v4.2.2 kullanıyordum ve orada varsayılan olarak üste alınmadığınız başka bir sayfaya gittiğinizde Bu nedenle, gezinme sonrasında kullanıcıyı manuel olarak sayfanın üstüne götürmeliyiz, ancak v5.0.1 tepki yönlendiricisi dom, kaydırma geri yüklemesini kutudan çıkarmayı durdurdu, çünkü belgelerine göre tarayıcılar desteklemeye başladığını söylüyorlar bu özellik varsayılan olarak ve reaktif yönlendirici-dom'un en son sürümüyle gezinmeden sonra sayfanın en üstüne çıkacaksınız.
Vishal Shetty

1
@Toxnyc böylece pencere nesnesini kullanmak Javascript nedir, Eğer reaksiyon Javascript'in üstünde ise, o zaman perde arkasında React Eklentisi herhangi birini kullansanız bile, sadece Javascript ve pencere nesnesini kullanacak, bilgim tepki belgesine sahip değil pencere ekranının ayrıntılarını alabileceğimiz herhangi bir şey. çalışmasını sağlamak için Javascript ile gitmeliyiz.
Vishal Shetty

13

Bu, refs kullanılarak ele alınabilir ve muhtemelen gerçekleştirilmelidir :

"... ReactDOM.findDOMNode'u bir" kaçış kapağı "olarak kullanabilirsiniz, ancak kapsülleme işlemini bozduğundan ve hemen hemen her durumda kodunuzu React modeli içinde yapılandırmanın daha net bir yolu olduğu için bunu önermiyoruz."

Örnek kod:

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

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

Harika çalışıyor. Teşekkürler. Açık olmak gerekirse, render ifademin <div ref={(ref) => this._div = ref} />ilk <div>basamağını koydum. Renderimin geri kalanı tamamen aynı kalıyor.
Josh F

Tarzlanmış bileşenler kullanıyorsanız "ref" yerine "innerRef" kullanmanız gerekir. Harika bir çözüm
furcicm

Tamamen çalışıyor. Üzerinde çalıştığım şey için, daha da basit olabilirdim <div ref="main">ve sonrathis.refs.main.scrollTop=0
chuckfactory

2
@chuckfactory dizeleri kullanarak refs ayarı muhtemelen bir noktada kaldırılacak ve aslında öğrenmek isteyebileceğiniz bazı ilginç dezavantajları var. news.ycombinator.com/edit?id=12093234
NJensen

10

Bunu yönlendiricide şu şekilde yapabilirsiniz:

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'));

onUpdate={() => window.scrollTo(0, 0)}Kaydırma üst koydu. Daha fazla bilgi için: kod bağlantısı


Her bir bileşenin kendisini işlemesini sağlamak yerine yönlendiricide yalnızca küçük bir kod değişikliği gerektiren zarif bir çözüm. <3
alengel

Maalesef, her yeni rotada yangınları güncelleyinParam belirli bir rotaya yönlendirildi. Örneğin, bir grup görüntü içeren bir sayfanız varsa ve rotayı değiştirmek için tıklatıldığında görüntüyü bir modda genişletebiliyorsanız, /somePage/:imgIdyukarı kayar :(. Belirli güzergahlarda / parametrelerde onUpdate olayı?
connected_user

Bunu denediğimde, TypeScript HashRouter'ın aksesuarlarında bulunmadığından şikayet etti onUpdate... Birisi aynı sorunla karşılaşırsa: Daha sonra açıklanan ScrollToTop çözümünü (ve benim için mükemmel çalışan tepki yönlendirici dokümanlar) kullandım.
Nicole

9

Kanca kullananlar için aşağıdaki kod çalışacaktır.

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

Not: useEffect'i doğrudan da içe aktarabilirsiniz: import { useEffect } from 'react'


1
[]İkinci parametre aracı olarak yalnızca ilk siz olmadan denedi kılmasıdır üzerine olur?
Powderham

8

ComponentDidUpdate / ComponentDidMount dosyasını çoğaltmadan pencere kaydırma konumunun sıfırlanmasını istediğiniz bağlı bileşenleri seçmenize izin veren başka bir yaklaşım daha var.

Aşağıdaki örnek Blog bileşenini ScrollIntoView () ile sarmaktadır, böylece Blog bileşeni takıldığında rota değişirse, HOC'nin ComponentDidUpdate penceresi kaydırma konumunu güncelleyecektir.

Herhangi bir rota değişikliğinde, bir pencere sıfırlamasını tetikleyecek şekilde tüm uygulamanın üzerine kolayca sarabilirsiniz.

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>
);

Yukarıdaki örnek harika çalışıyor, ancak taşındıysanız react-router-dom, aşağıdakileri oluşturarak yukarıdakileri basitleştirebilirsiniz.HOC taşındıysanız, bileşeni saran .

Bir kez daha, rotalarınız üzerinde kolayca kolayca sarabilirsiniz ( componentDidMountyöntemi, componentDidUpdateyukarıda yazılı yöntem örneği koduna değiştirmenin yanı sıra ScrollIntoView,withRouter ).

konteyner / ScrollIntoView.js

import { PureComponent, Fragment } from "react";

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

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

export default ScrollIntoView;

bileşenleri / Home.js

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

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

ScrollIntoView.js bana "kullanılmayan ifade, bir atama veya işlev çağrısı bekleniyor" hatası veriyor
EX0MAK3R

@ EX0MAK3R - Cevap güncellendi.
Matt Carlotta

7

Benim için işe yarayan tek şey bu (ES6 sınıfı bileşeniyle):

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

Aynı şekilde. Diğer tüm çözümleri denedim ve bu benim için çalışan tek çözümdü.
Erik James Robles

7

Tepki-yönlendirici dokümanlar açıklanan kod tepki yönlendirici ScrollToTop bileşeni kullanıyorum

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

Tek Routes dosyasında kodu değiştiriyorum ve bundan sonra her bileşende kod değiştirmeye gerek yok.

Örnek Kod -

Adım 1 - ScrollToTop.js Bileşeni Oluşturun

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)

Adım 2 - App.js dosyasına ScrollToTop Component öğesini ekleyin. <Router

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

gerçekten iyi bir çözüm! Eğer rotalarınız varsa sadece rotanızın üstünde, ama Router altında render. Her bir bileşeni değiştirmek zorunda kalmadım.
döküntü

5

Kanca çözümü :

  • ScrollToTop kancası oluşturma

    import { useEffect } from "react";
    import { withRouter } from "react-router-dom";

    const ScrollToTop = ({ children, location: { pathname } }) => {
      useEffect(() => {
        window.scrollTo({
          top: 0,
          left: 0,
          behavior: "smooth"
        });
      }, [pathname]);

      return children || null;
    };

    export default withRouter(ScrollToTop);
  • Uygulamanızı onunla sarın

    <Router>
        <ScrollToTop>
           <App />
        </ScrollToTop>
    </Router>

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



4

Yukarıdakilerin hepsi benim için işe yaramadı - neden olduğundan emin değilim:

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

HEADER başlık öğemin kimliği olduğu yerde çalıştı


Bir useEffect kanca kullandım ama bu benim için bir Gatsby projesinde harika çalıştı. Teşekkürler!
jj0b

4

Eğer tüm yapmak isteyenler burada basit bir şeyse, herkes için işe yarayacak bir çözüm

bu mini işlevi ekle

scrollTop()
{
    window.scrollTo({
        top: 0,
        behavior: "smooth"
    });
}

işlevi sayfanın altbilgisinden aşağıdaki gibi çağırın

<a className="scroll-to-top rounded" style={{display: "inline"}} onClick={this.scrollTop}>TOP</a>

güzel stiller eklemek istiyorsanız css burada

.scroll-to-top {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  display: none;
  width: 2.75rem;
  height: 2.75rem;
  text-align: center;
  color: #fff;
  background: rgba(90, 92, 105, 0.5);
  line-height: 46px;
}


kod snippet'i çalışmıyor gibi görünüyor. Ama çözüm benim için çalıştı. Teşekkürler ve şerefe!
globefire

3

React Hooks kullanıyorum ve yeniden kullanılabilir bir şey değil, aynı zamanda (renderden sonra değil) herhangi bir zamanda arayabileceğim bir şey istedim.

// utils.js
export const useScrollToTop = (initialScrollState = false) => {
  const [scrollToTop, setScrollToTop] = useState(initialScrollState);

  useEffect(() => {
    if (scrollToTop) {
      setScrollToTop(false);
      try {
        window.scroll({
          top: 0,
          left: 0,
          behavior: 'smooth',
        });
      } catch (error) {
        window.scrollTo(0, 0);
      }
    }
  }, [scrollToTop, setScrollToTop]);

  return setScrollToTop;
};

Ardından kancayı kullanmak için şunları yapabilirsiniz:

import { useScrollToTop } from 'utils';

const MyPage = (props) => {
  // initialise useScrollToTop with true in order to scroll on page load 
  const setScrollToTop = useScrollToTop(true);

  ...

  return <div onClick={() => setScrollToTop(true)}>click me to scroll to top</div>
}

Harika bir çözüm!
Nick

2

Bunu mobil cihazlar için yapıyorsanız , en azından kromla, altta beyaz bir çubuk göreceksiniz.

Bu, URL çubuğu kaybolduğunda olur. Çözüm:

Yükseklik / dk. Yükseklik: % 100 değerini yükseklik / dk . Yükseklik: 100vh olarak değiştirin .

Google Geliştirici Dokümanları


1

Yukarıdaki cevapların hiçbiri şu anda benim için çalışmıyor. O .scrollTokadar geniş uyumlu değil gibi görünüyor .scrollIntoView.

Bizim App.js olarak, içinde componentWillMount()biz ekledi

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

Bizim için evrensel olarak çalışan tek çözüm budur. kök bizim App kimliğidir. "Düzgün" davranış her tarayıcıda / cihazda çalışmaz. 777 zaman aşımı biraz muhafazakar, ancak her sayfada çok fazla veri yüklüyoruz, bu yüzden test ederek gerekliydi. Çoğu uygulama için daha kısa 237 işe yarayabilir.


1

Bu konuya, Bağlantısı Erişim Yönlendiricisi'nin üzerine kurulmuş Gatsby ile bir site oluşturmakla karşılaştım. Bunun varsayılan davranıştan ziyade yapılması gereken bir değişiklik olması tuhaf görünüyor.

Her neyse, yukarıdaki çözümlerin çoğunu denedim ve benim için gerçekten işe yarayan tek şey:

document.getElementById("WhateverIdYouWantToScrollTo").scrollIntoView()

Bunu bir useEffect'e koydum, ancak kolaylıkla componentDidMount'a koyabilir veya istediğiniz herhangi bir şekilde tetikleyebilirsiniz.

Window.scrollTo (0, 0) 'in neden benim (ve diğerleri) için işe yaramadığından emin değilim.


0

Tüm çözümler kaydırmayı eklemek componentDidMountveyacomponentDidUpdate DOM ile DOM ile .

Tüm bunları yaptım ve işe yaramadı.

Yani, benim için iyi çalışan başka bir yol buldum.

componentDidUpdate() { window.scrollTo(0, 0) } Başlığa eklendiğinde , benimki <Switch></Switch>öğenin dışında. Sadece app ücretsiz. İşler.

Ayrıca bazı ScrollRestoration hakkında da buldum şeyleri , ama şimdi tembelim. Ve şimdilik bunu "DidUpdate" yolunda tutacağım.

Umarım yardımcı olur!

dikkatli ol


0

Bu kod neden olacaktır pürüzsüz bir davranış üzerindeki kaydırma :

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

ScrollIntoView () içine diğer parametreleri iletebilirsiniz Aşağıdaki sözdizimi kullanılabilir:

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

alignToTop Optional Bir Boole değeri:

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 İsteğe Bağlı Aşağıdaki özelliklere sahip bir Nesnedir :

*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".

Daha fazla ayrıntıyı burada bulabilirsiniz: MDN belgeleri


0

Yukarıdaki cevapların hiçbiri şu anda benim için çalışmıyor. O .scrollTokadar geniş uyumlu değil ki çıkıyor.scrollIntoView.

Bizim App.js olarak, içinde componentWillMount()biz ekledi

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

Bizim için evrensel olarak çalışan tek çözüm budur. rootbizim App kimliğidir. "Düzgün" davranış her tarayıcıda / cihazda çalışmaz. 777 zaman aşımı biraz muhafazakar, ancak her sayfada çok fazla veri yüklüyoruz, bu yüzden test ederek gerekliydi. Çoğu uygulama için daha kısa 237 işe yarayabilir.


0

Bir sayfa, kitap başına kitap gibi bir bölüm oluşturduğunuzu varsayarsak, tek yapmanız gereken bunu kodunuza eklemektir. Bu benim için sihir gibi çalıştı.

    componentDidUpdate(prevProps) {
      if (prevProps.currentChapter !== this.props.currentChapter) {
        window.scrollTo(0, 0);
      }
    }

Bu şekilde, oluşturulan bileşen için bir ref oluşturmanıza gerek kalmaz.


0

Yaptığım şey bu:

...
useEffect(() => ref.current.scrollTo(0, 0));
const ref = useRef()

       return(
         <div ref={ref}>
           ...
         </div>
        )
...

0

Kullanabilirsin, bu benim için çalışıyor.

import React, { useEffect } from 'react';

useEffect(() => {
    const body = document.querySelector('#root');

    body.scrollIntoView({
        behavior: 'smooth'
    }, 500)

}, []);

-1

Böyle bir şey benim için bir bileşen üzerinde çalıştı:

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

Sonra hangi fonksiyon güncellemelerle ilgileniyorsa:

this.refs.scroller.scrollTop=0

-1

Benim için hiçbir şey işe yaramadı ama:

componentDidMount(){

    $( document ).ready(function() {
        window.scrollTo(0,0);
    });
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.