Bir öğeye nasıl geçilir?


183

Her kaydırma yaptığımda bir dizi mesajı çeken bir sohbet widget'ım var. Şimdi karşı karşıya olduğum sorun mesajlar yüklendiğinde kaydırıcı üst sabit kalır. Önceki dizinin son dizin öğesine odaklanmak istiyorum. Dizini geçerek dinamik referanslar yapabileceğimi anladım, ancak bunu elde etmek için ne tür kaydırma işlevinin kullanılacağını da bilmem gerekir.

 handleScrollToElement(event) {
    const tesNode = ReactDOM.findDOMNode(this.refs.test)
    if (some_logic){
      //scroll to testNode      
    }
  }

  render() {

    return (
      <div>
        <div ref="test"></div>
      </div>)
  }

1
Paketlenmiş bir çözüm için: npmjs.com/package/react-scroll-to-component
tokland

Yanıtlar:


306

React 16.8 +, İşlevsel bileşen

import React, { useRef } from 'react'

const scrollToRef = (ref) => window.scrollTo(0, ref.current.offsetTop)   
// General scroll to element function

const ScrollDemo = () => {

   const myRef = useRef(null)
   const executeScroll = () => scrollToRef(myRef)

   return (
      <> 
         <div ref={myRef}>I wanna be seen</div> 
         <button onClick={executeScroll}> Click to scroll </button> 
      </>
   )
}

StackBlits ile ilgili tüm demo için burayı tıklayın

React 16.3 +, Sınıf bileşeni

class ReadyToScroll extends Component {

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

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

    scrollToMyRef = () => window.scrollTo(0, this.myRef.current.offsetTop)   
    // run this method to execute scrolling. 

}

Sınıf bileşeni - Ref geri arama

class ReadyToScroll extends Component {
    myRef=null
    // Optional

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

    scrollToMyRef = () => window.scrollTo(0, this.myRef.offsetTop)
    // run this method to execute scrolling. 
}

String refs kullanmayın.

Dize ref'leri performansa zarar verir, oluşturulamaz ve çıkış yolundadır (Ağu 2018).

string refs'nin bazı sorunları vardır, eski olarak kabul edilir ve gelecekteki sürümlerden birinde kaldırılması muhtemeldir. [Resmi Reaksiyon belgeleri]

kaynak1 kaynak2

İsteğe bağlı: Kaydırma animasyonunu yumuşat

/* css */
html {
    scroll-behavior: smooth;
}

Ref çocuğa geçme

Ref'nin bir tepki bileşenine değil dom dom öğesine eklenmesini istiyoruz. Bu yüzden bir alt bileşene geçirirken prop ref adını veremeyiz.

const MyComponent = () => {
    const myRef = useRef(null)
    return <ChildComp refProp={myRef}></ChildComp>
} 

Ardından ref pervanesini bir dom elemanına takın.

const ChildComp = (props) => {
    return <div ref={props.refProp} />
}

5
window.scrollTo(0, offsetTop)tarayıcılar arasında daha iyi destek ile daha iyi bir seçenektir
MoMo

1
Örnekleminizde tutarlı olduğunuzdan emin olabilirsiniz. MyRef'ten başlıyoruz, domRef ile mi gidiyoruz ve tesNode ile mi bitiyoruz? Bu oldukça kafa karıştırıcı
Louis Lecocq

4
Açıkçası, ancak bunun sadece herhangi bir React bileşeni için değil, sadece yerel DOM öğeleri için çalıştığını belirtmek önemlidir.
18:19

1
@ jpunk11 Cevabımı yeni güncelledim. Güncellenmiş yanıt, alt sınıf bileşenindeki dom öğesine nasıl kaydırılacağını açıklar.
Ben Carp

2
@SimonFranzen Güncellenmiş cevabım olan TLDR sınıfı bileşen durumuma bir göz atın. ScrollToMyRef çağrıldığında ref'yi eklediğiniz çocuğa kaydırılır. Yöntemi farklı bir alt bileşene geçirebilir ve oradan tetikleyebilirsiniz.
Ben Carp

55

bu benim için çalıştı

this.anyRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' })

EDIT: Bu yorumlara dayanarak bunu genişletmek istedim.

const scrollTo = (ref) => {
  if (ref /* + other conditions */) {
    ref.scrollIntoView({ behavior: 'smooth', block: 'start' })
  }
}

<div ref={scrollTo}>Item</div>

1
nereye koymak
su_sundariya

yaşam döngüsü yöntemi veya yapıcı
su_sundariya

1
Tıkır tıkır çalışıyor. Yukarıdakilerin hiçbiri benim için çalışmıyor, bu cevap kabul edilmelidir!
Shin

1
Benim için çalıştı, sadece 'start' 'block' parametresinin varsayılan değeridir.
Liron Lavi

@Ben Carp'ın cevabı olmazsa bu benim için çalıştı.
Jason Masters

37

Sadece zaten belirledik elemanın üst konumunu bulmak https://www.w3schools.com/Jsref/prop_element_offsettop.asp sonra üzerinden bu pozisyona kaydırma scrollToyöntemiyle https://www.w3schools.com/Jsref/met_win_scrollto.asp

Böyle bir şey işe yaramalı:

handleScrollToElement(event) {
  const tesNode = ReactDOM.findDOMNode(this.refs.test)
  if (some_logic){
    window.scrollTo(0, tesNode.offsetTop);
  }
}

render() {

  return (
    <div>
      <div ref="test"></div>
    </div>)
}

GÜNCELLEME:

çünkü v16.3 tepkiReact.createRef() tercih edilir

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

handleScrollToElement(event) {
  if (<some_logic>){
    window.scrollTo(0, this.myRef.current.offsetTop);
  }
}

render() {

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

2
Bu daha iyi cevap. Kullanmak ReactDOM.findDomNode()daha iyi bir uygulamadır - React bileşenleri yeniden oluşturduğundan, kimliğine göre aldığınız bir div işlevi çağırdığınızda varolmayabilir
Good Idea

4
Resmi belgelere göre kullanmaktan kaçınmaya çalışmalısınız findDOMNode. Çoğu durumda, DOM düğümüne bir ref ekleyebilir ve findDOMNodehiç kullanmaktan kaçınabilirsiniz .
Facyo Kouch

1
This.refs komutunun dize eşleme ile kullanılmasının kullanımdan kaldırıldığını unutmayın: stackoverflow.com/questions/43873511/…
Himmet Avsar

1
Not: Bunun this.myRef.current.scrollIntoView()yerine kullanmak zorunda kaldım window.scrollTo(0, this.myRef).
Babbz77

14

FindDOMNode kullanımı nihayetinde kullanımdan kaldırılacaktır.

Tercih edilen yöntem geri arama referanslarını kullanmaktır.

github eslint


3
Lütfen bağlantılı materyalin ilgili kısmını ekleyin, böylece kaldırılması durumunda cevabınız işe yaramaz.
totymedli

12

Artık useRefreaksiyon kancası API'sından kullanabilirsiniz

https://reactjs.org/docs/hooks-reference.html#useref

deklarasyon

let myRef = useRef()

bileşen

<div ref={myRef}>My Component</div>

kullanım

window.scrollTo({ behavior: 'smooth', top: myRef.current.offsetTop })

Kodunuzu kullanmaya çalışıyorum. Görebiliyorum, (benim durumum için ayarlanmış) console.logifadenizi yürütüyor window.scrollToama yine de kaydırma değil. Bu bir React Bootstrap Modal kullandığımla ilgili olabilir mi?
robertwerner_sf

9

scrollIntoViewBelirli bir öğeye gitmek için yöntemi de kullanabilirsiniz .

handleScrollToElement(event) {
const tesNode = ReactDOM.findDOMNode(this.refs.test)
 if (some_logic){
  tesNode.scrollIntoView();
  }
 }

 render() {
  return (
   <div>
     <div ref="test"></div>
   </div>)
}

9

Partiye geç kalabilirim ama projeme doğru şekilde dinamik referanslar uygulamaya çalışıyordum ve bilinceye kadar bulduğum tüm cevaplar beğenime tatmin edici değil, bu yüzden bence bir çözüm buldum basit ve ref oluşturmak için yerel ve önerilen tepki yolunu kullanır.

Bazen belgelerin yazılma şeklinin, bilinen bir görüntüleme sayısına sahip olduğunuzu varsadığını ve çoğu durumda bu sayının bilinmediğini fark edersiniz, bu nedenle bu durumda sorunu çözmenin bir yoluna ihtiyacınız vardır, ihtiyacınız olan bilinmeyen sayıda görünüme dinamik referanslar oluşturun sınıfta göstermek

düşünebildiğim ve kusursuz çalışabildiğim en basit çözüm aşağıdaki gibi yapmaktı:

class YourClass extends component {

state={
 foo:"bar",
 dynamicViews:[],
 myData:[] //get some data from the web
}

inputRef = React.createRef()

componentDidMount(){
  this.createViews()
}


createViews = ()=>{
const trs=[]
for (let i = 1; i < this.state.myData.lenght; i++) {

let ref =`myrefRow ${i}`

this[ref]= React.createRef()

  const row = (
  <tr ref={this[ref]}>
<td>
  `myRow ${i}`
</td>
</tr>
)
trs.push(row)

}
this.setState({dynamicViews:trs})
}

clickHandler = ()=>{

//const scrollToView = this.inputRef.current.value
//That to select the value of the inputbox bt for demostrate the //example

value=`myrefRow ${30}`

  this[value].current.scrollIntoView({ behavior: "smooth", block: "start" });
}


render(){

return(
<div style={{display:"flex", flexDirection:"column"}}>
<Button onClick={this.clickHandler}> Search</Button>
<input ref={this.inputRef}/>
<table>
<tbody>
{this.state.dynamicViews}
<tbody>
<table>
</div>


)

}

}

export default YourClass

Bu şekilde kaydırma, aradığınız herhangi bir satıra gider.

şerefe ve umarım başkalarına yardımcı olur


8

Temmuz 2019 - Özel kanca / işlev

Özel bir kanca / işlev, uygulama ayrıntılarını gizleyebilir ve bileşenlerinize basit bir API sağlar.

React 16.8 + Fonksiyonel Bileşen

const useScroll = () => {
  const htmlElRef = useRef(null)
  const executeScroll = () => window.scrollTo(0, htmlElRef.current.offsetTop)

  return [executeScroll, htmlElRef]
}

Herhangi bir fonksiyonel bileşende kullanın.

const ScrollDemo = () => {
    const [executeScroll, htmlElRef] = useScroll()
    useEffect(executeScroll, []) // Runs after component mounts

    return <div ref={htmlElRef}>Show me</div> 
}

tam demo

React 16.3 + sınıfı Bileşeni

const utilizeScroll = () => {
  const htmlElRef = React.createRef()
  const executeScroll = () => window.scrollTo(0, htmlElRef.current.offsetTop)

  return {executeScroll, htmlElRef}
}

Herhangi bir sınıf bileşeninde kullanın.

class ScrollDemo extends Component {
  constructor(){
    this.elScroll = utilizeScroll()
  }

  componentDidMount(){
    this.elScroll.executeScroll()
  }

  render(){
    return <div ref={this.elScroll.htmlElRef}>Show me</div> 
  }
} 

Tam demo


7

Bu şekilde deneyebilirsiniz:

 handleScrollToElement = e => {
    const elementTop = this.gate.offsetTop;
    window.scrollTo(0, elementTop);
 };

 render(){
  return(
      <h2 ref={elem => (this.gate = elem)}>Payment gate</h2>
 )}

Muhtemelen this.gate.offsetTop yerine e.offsetTop istemenize rağmen this.gate işlevine geçmeniz iyi bir çözümdür.
KingOfHypocrites

5

Gibi bir şey kullanabilirsiniz componentDidUpdate

componentDidUpdate() {
  var elem = testNode //your ref to the element say testNode in your case; 
  elem.scrollTop = elem.scrollHeight;
};

3
reaksiyonda element id kullanılması tercih edilmez. Sanal dom konseptini kırıyor
iamsaksham

Yaşam döngüsü yöntemini kullanmak, kodu çalıştırmak için NE ZAMAN / NEREDE kadar ileri gitmenin yoludur. Ama muhtemelen bu kodda gördüğünüz diğer yöntemleri gerçek kod için kullanmak istersiniz
Dameo

4

Basit bir senaryom vardı, Kullanıcı Malzeme UI Navbar'ımdaki menü öğesini tıkladığında onları sayfadaki bölüme kaydırmak istiyorum. Ben refs kullanmak ve tüm bileşenleri onları iplik ama ben kod kırılgan yapar çünkü iplik sahne sahne birden fazla bileşen nefret ediyorum.

Reaksiyon bileşenimde vanilya JS kullandım, gayet iyi çalışıyor. Kaydırmak istediğim öğeye bir kimlik yerleştirdim ve başlık bileşenime bunu yaptım.

const scroll = () => {
  const section = document.querySelector( '#contact-us' );
  section.scrollIntoView( { behavior: 'smooth', block: 'start' } );
};

2

Bu adımları takip et:

1) yükleyin:

npm install react-scroll-to --save

2) paketi alın:

import { ScrollTo } from "react-scroll-to";

3) Kullanımı:

class doc extends Component {
  render() {
    return(
      <ScrollTo>
        {({ scroll }) => (
          <a onClick={() => scroll({ x: 20, y: 500, , smooth: true })}>Scroll to Bottom</a>
        )}
      </ScrollTo>
    )
  }
}

2

İşte Sınıf Bileşen bu sorunu çözmek için kullanabileceği pasajı kodu:

Bu yaklaşım ref'yi kullandı ve aynı zamanda hedef ref'ye sorunsuzca kaydırıyor

import React, { Component } from 'react'

export default class Untitled extends Component {
  constructor(props) {
    super(props)
    this.howItWorks = React.createRef() 
  }

  scrollTohowItWorks = () =>  window.scroll({
    top: this.howItWorks.current.offsetTop,
    left: 0,
    behavior: 'smooth'
  });

  render() {
    return (
      <div>
       <button onClick={() => this.scrollTohowItWorks()}>How it works</button>
       <hr/>
       <div className="content" ref={this.howItWorks}>
         Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nesciunt placeat magnam accusantium aliquid tenetur aspernatur nobis molestias quam. Magnam libero expedita aspernatur commodi quam provident obcaecati ratione asperiores, exercitationem voluptatum!
       </div>
      </div>
    )
  }
}

2

En güzel yolu kullanmaktır element.scrollIntoView({ behavior: 'smooth' }). Bu, öğeyi hoş bir animasyonla görünüme kaydırır.

React'lerle birleştirdiğinizde useRef(), şu şekilde yapılabilir.

import React, { useRef } from 'react'

const Article = () => {
  const titleRef = useRef()

  function handleBackClick() {
      titleRef.current.scrollIntoView({ behavior: 'smooth' })
  }

  return (
      <article>
            <h1 ref={titleRef}>
                A React article for Latin readers
            </h1>

            // Rest of the article's content...

            <button onClick={handleBackClick}>
                Back to the top
            </button>
        </article>
    )
}

Bir React bileşenine gitmek istediğinizde, ref'yi işlenen öğeye iletmeniz gerekir. Bu makale sorunun derinliklerine inecektir .


Bu çok daha iyi. Başlangıçta yapıyordum (ref) => window.scrollTo(0, ref.current.offsetTop) ama sonra sadece üstten küçük bir ofset alıp hedefe ulaşmıyordum. Bunun nedeni, ref'nin konumunun başlangıçta hesaplanan ve daha sonra güncellenmeyen biri olması gerektiğidir. Kabul ettiğiniz cevap sorunumu çözerken kabul edilen cevap gelmedi.
Willy

1

Benim için ne işe yaradı:

class MyComponent extends Component {
    constructor(props) {
        super(props);
        this.myRef = React.createRef(); // Create a ref    
    }

    // Scroll to ref function
    scrollToMyRef = () => {
        window.scrollTo({
            top:this.myRef.offsetTop, 
            // behavior: "smooth" // optional
        });
    };

    // On component mount, scroll to ref
    componentDidMount() {
        this.scrollToMyRef();
    }

    // Render method. Note, that `div` element got `ref`.
    render() {
        return (
            <div ref={this.myRef}>My component</div>
        )
    }
}

1

Sadece bir çözüm, bu çözümleri Material UI bileşenleri üzerinde çalışmak için alamadım. currentMülkleri yok gibi görünüyor .

divBileşenlerimin arasına bir boşluk ekledim ve ref pervanesini buna ayarladım.


0
 <div onScrollCapture={() => this._onScrollEvent()}></div>

 _onScrollEvent = (e)=>{
     const top = e.nativeEvent.target.scrollTop;
     console.log(top); 
}


0

Kimliğini "step2Div" olduğu bir div'a sorunsuz kaydırmak için bir onclick işlevi içinde bunu kullandım.

let offset = 100;
window.scrollTo({
    behavior: "smooth",
    top:
    document.getElementById("step2Div").getBoundingClientRect().top -
    document.body.getBoundingClientRect().top -
    offset
});
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.