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


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.