Як прокрутити елемент?


181

У мене є віджет для чату, який піднімає масив повідомлень щоразу, коли я прокручую вгору. Проблема, з якою я стикаюся зараз, полягає в тому, що слайдер залишається нерухомим у верхній частині під час завантаження повідомлень. Я хочу, щоб він зосередився на останньому елементі індексу з попереднього масиву. Я зрозумів, що я можу робити динамічні рефлекси, проходячи індекс, але мені також слід знати, яку функцію прокрутки використовувати для досягнення цього

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

  render() {

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

Відповіді:


301

Реагує 16,8 +, функціональний компонент

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

Реакція 16.3 +, компонент класу

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. 

}

Компонент класу - Відкликання зворотного виклику

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. 
}

Не використовуйте рядкові реф.

Рядки, що відбивають шкідливість, не підлягають компіляції, і вони виходять (серпень 2018).

Посилання на рядки мають деякі проблеми, вважаються застарілими і, ймовірно, будуть видалені в одному з майбутніх версій. [Офіційна документація на реагування]

ресурс1 ресурс2

Необов’язково: згладити анімацію прокрутки

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

Проходження реф. На дитину

Ми хочемо, щоб посилання було приєднано до елемента купола, а не до компонента, що реагує. Отже, передаючи його дочірньому компоненту, ми не можемо назвати реквізит підтримки.

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

Потім прикріпіть опорну опору до елемента dom.

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

5
window.scrollTo(0, offsetTop)є кращим варіантом з кращою підтримкою серед поточних браузерів
MoMo

1
Можна переконатися, що ви послідовні у своєму прикладі. Ми починаємо від myRef, йдемо з domRef і закінчуємо tesNode ?. Це досить заплутано
Луї Лекок

4
Очевидно після факту, але важливо зазначити, що це працює лише для нативних DOM-елементів, а не будь-якого компонента React.
jpunk11

1
@ jpunk11 Я щойно оновив свою відповідь. Оновлена ​​відповідь пояснює, як прокрутити до елемента dom, який знаходиться в складі дочірнього класу.
Бен Карп

2
@SimonFranzen Погляньте на мою оновлену відповідь - корпус компонентів TLDR. Коли викликається scrollToMyRef, він прокручується до дитини, до якої ви додали запит. Ви можете передати метод іншому дочірньому компоненту та запустити його звідти.
Бен Карп

55

це працювало для мене

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

EDIT: Я хотів розширити це на основі коментарів.

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

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

1
куди це поставити
su_sundariya

методом або конструктором життєвого циклу
su_sundariya

1
Працює як шарм. Жодне з перерахованого вище для мене не працює, на це слід прийняти відповідь!
Шин

1
Працював для мене, просто зауважте, що "пуск" - це значення за замовчуванням параметра "блок".
Лірон Лаві

Це працювало для мене, коли відповідь @Ben Carp не відповіла.
Джейсон Мастерс

37

Просто знайдіть верхню позицію елемента, який ви вже визначили https://www.w3schools.com/Jsref/prop_element_offsettop.asp, а потім прокрутіть до цього положення scrollToметодом https://www.w3schools.com/Jsref/met_win_scrollto.asp

Щось подібне повинно працювати:

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

ОНОВЛЕННЯ:

так React v16.3React.createRef() є кращим

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
Це краща відповідь. Використання ReactDOM.findDomNode()є кращою практикою - оскільки React повторно надає компоненти, div, який ви просто отримаєте за його ідентифікатором, може не існувати до моменту виклику функції
Good Idea

4
Відповідно до офіційної документації, ви повинні намагатися уникати використання findDOMNode. У більшості випадків ви можете приєднати посилання на вузол DOM і findDOMNodeвзагалі уникати використання .
Фасіо Куч

1
Зауважте, що використання цього.refs шляхом відображення рядків застаріле, див.: Stackoverflow.com/questions/43873511/…
Хіммет Авсар

1
Примітка: мені довелося використовувати this.myRef.current.scrollIntoView()замість цього window.scrollTo(0, this.myRef).
Babbz77

14

Використання вузла findDOMN з часом буде застарілим.

Кращим методом є використання зворотних зворотних дзвінків.

github eslint


3
Будь ласка, включіть відповідну частину пов'язаного матеріалу, щоб у випадку, якщо вас видаляють, ваша відповідь не стане марною.
totymedli

12

Тепер ви можете користуватися useRefAPI API для реагування на гак

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

декларація

let myRef = useRef()

компонент

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

Використовуйте

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

Я намагаюся використовувати ваш код. Я бачу, завдяки console.logцьому він виконує ваше window.scrollToтвердження (адаптоване до мого випадку), але воно не прокручується. Це може бути пов’язано з тим, що я використовую React Bootstrap Modal?
robertwerner_sf

9

Ви також можете використовувати scrollIntoViewметод для прокрутки до заданого елемента.

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

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

9

Я можу запізнитися на вечірку, але я намагався належним чином реалізувати динамічні рефлексиї на мій проект, і всі відповіді, які я знайшов, поки не знаю, не тихо задовольняють моє сподобання, тому я придумав рішення, яке, на мою думку, є простий і використовує рідний і рекомендований спосіб реагування для створення реф.

іноді ви виявляєте, що спосіб написання документації передбачає, що у вас є відома кількість переглядів, і в більшості випадків це число невідоме, тому вам потрібен спосіб вирішити проблему в цьому випадку, створити динамічні рефлекси на невідому кількість переглядів, які вам потрібні показати в класі

тож найпростішим рішенням, про яке я міг придумати і працював бездоганно, було зробити наступне

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

таким чином прокрутка перейде до того місця, де ви шукаєте ..

вітає і сподівається, що це допомагає іншим


8

Липень 2019 - Виділений гачок / функція

Виділений гак / функція може приховувати деталі реалізації та надає простий API вашим компонентам.

Реагуйте 16,8 + функціональний компонент

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

  return [executeScroll, htmlElRef]
}

Використовуйте його в будь-якому функціональному компоненті.

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

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

повна демонстрація

Реагує 16.3 + компонент класу

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

  return {executeScroll, htmlElRef}
}

Використовуйте його в будь-якому компоненті класу.

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

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

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

Повна демонстрація


7

Ви можете спробувати так:

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

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

Хороше рішення, хоча ви, мабуть, хочете e.offsetTop, а не this.gate.offsetTop, а потім передайте this.gate функції.
KingOfHypocrites

5

Можна використовувати щось подібне componentDidUpdate

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

3
Я думаю, що використання елемента елемента не є переважним у реакції. Це порушує концепцію віртуального дому
iamsaksham

Використання методу життєвого циклу - це спосіб пройти так далеко, КОЛИ / ГДЕ запускати код. Але, ймовірно, ви хочете використовувати інші методології, які ви бачите у цій відповіді, для фактичного коду
Дамео

3

У мене був простий сценарій, коли користувач натискає на пункт меню в моєму інтерфейсі користувача Navbar, я хочу прокрутити їх до розділу на сторінці. Я міг би використовувати реф-файли і пропускати їх через усі компоненти, але я ненавиджу реквізит для прорізування реквізиту декількох компонентів, оскільки це робить код крихким.

Я щойно використовував ванільний JS в своєму реагуючому компоненті, виявляється, він працює чудово. Розмістив ідентифікатор на елементі, до якого я хотів прокрутити, і в своєму компоненті заголовка я це тільки зробив.

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

2

Виконайте такі дії:

1) Встановіть:

npm install react-scroll-to --save

2) Імпортуйте пакет:

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

3) Використання:

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

2

Ось фрагмент коду компонента класу, який ви можете використовувати для вирішення цієї проблеми:

Цей підхід використовував посилання, а також плавно прокручує цільовий номер

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

1

Що для мене спрацювало:

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

Лише вгору я не міг змусити ці рішення працювати над компонентами інтерфейсу Material. Схоже, у них цього немаєcurrent власності.

Я просто додав порожнє divсеред своїх компонентів і встановив додаткову підтримку.


1

Найприємніший спосіб - це використовувати element.scrollIntoView({ behavior: 'smooth' }). Це прокручує елемент для перегляду з приємною анімацією.

Якщо ви комбінуєте його з React useRef(), це можна зробити наступним чином.

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

Коли ви хочете, щоб прокрутити до компонента React, вам потрібно переадресувати його на виведений елемент. Ця стаття зануриться глибше в проблему .


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

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


0

Я використовував це всередині функції onclick, щоб плавно прокручувати діл, де його ідентифікатор "step2Div".

let offset = 100;
window.scrollTo({
    behavior: "smooth",
    top:
    document.getElementById("step2Div").getBoundingClientRect().top -
    document.body.getBoundingClientRect().top -
    offset
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.