ReactJS как прокручивать элемент

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

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

  render() {

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

Ответ 1

Реакция 16.8+, функциональный компонент

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 (
      <> {/* React.Fragment*/}
         <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()   // Create a ref object 
    }

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

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

}

Компонент класса - ссылка обратного вызова

class ReadyToScroll extends Component {

    constructor(props){   // Optional, declare a class field to improve readability
        super(props)
        this.myRef=null    
    }

    render() {
        return <div ref={ (ref) => this.myRef=ref }></div>
    }   // Attach the dom element to a class field

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

Не используйте строковые ссылки.

Строковые ссылки вредят производительности, не поддаются компоновке и находятся на выходе (август 2018 г.).

Строковые ссылки имеют некоторые проблемы, считаются устаревшими и могут быть удаленным в одном из будущих выпусков. [Официальная документация React]

resource1resource2

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

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

Передача ссылки ребенку

Мы хотим, чтобы ссылка была прикреплена к элементу dom, а не к компоненту реакции. Таким образом, передавая его дочернему компоненту, мы не можем назвать опорный реф.

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

Затем прикрепите опорный элемент к элементу dom.

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

Ответ 2

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

Примерно так должно работать:

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.3, React.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>)
}

Ответ 3

это сработало для меня

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

Ответ 4

Использование findDOMNode в конечном итоге будет устаревшим.

Предпочтительным методом является использование обратных ссылок.

Github Eslint

Ответ 5

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

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

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

Ответ 6

Возможно, я опоздал на вечеринку, но я пытался правильно реализовать динамические ссылки в своем проекте, и все ответы, которые я нашел до тех пор, пока не узнали, не удовлетворяют меня по вкусу, поэтому я нашел решение, которое, мне кажется, простой и использует родной и рекомендуемый способ реагирования для создания ссылки.

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

поэтому самое простое решение, которое я мог придумать и работать безупречно, заключалось в следующем

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

Таким образом, свиток перейдет в любую строку, которую вы ищете..

ура и надеюсь, что это помогает другим

Ответ 7

Вы можете попробовать так:

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

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

Ответ 8

Теперь вы можете использовать useRef из 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 })

Ответ 9

Вы можете использовать что-то вроде componentDidUpdate

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

Ответ 10

Используйте композицию функций, чтобы скрыть детали реализации

Реакция 16.8 + функциональный компонент

крючок useScroll

Следующий хук useScroll скрывает детали реализации dom и предоставляет простой API.

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

  return [executeScroll, htmlElRef]
}

Тогда вы можете легко прокрутить ваши функциональные компоненты.

const ScrollDemo = () => {
    const [executeScroll, elementToScrollRef] = useScroll()

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

}

Нажмите здесь для полной демонстрации на StackBlitz

Реагировать 16,3 + класс Компонент

utilizeScroll

Функция compositioin может быть использована и в компонентах класса.

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()
  }
  render(){
        return (
        <> 
          <div ref={this.elScroll.htmlElRef}>I wanna be seen</div> 
          <button onClick={this.elScroll.executeScroll} >Click to scroll </button> 
        </>
      )
  }
} 

Нажмите здесь для полной демонстрации на StackBlitz

Ответ 11

Что сработало для меня:

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

Ответ 12

После тестирования нескольких решений, прокрутите список компонентов.
Используя $ внутри класса Component, он по-прежнему позволяет применять прокрутку к любому элементу с помощью селектора xpath.

import React from 'react';
import $ from "jquery"

scrollToElem() {

  var elem= $( ".selector" )[0];
  $('html, body').animate({
      scrollTop: $(elem).offset().top
    }, 1800); 
}

Ответ 13

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

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