要素までスクロールする方法は?


181

上にスクロールするたびに一連のメッセージを表示するチャットウィジェットがあります。私が今直面している問題は、メッセージが読み込まれるときにスライダーが上部に固定されたままであることです。前の配列の最後のインデックス要素に焦点を当てたいです。インデックスを渡すことで動的参照を作成できることを理解しましたが、それを達成するために使用するスクロール関数の種類を知る必要もあります

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

  render() {

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

1
バンドルされたソリューションの場合:npmjs.com/package/react-scroll-to-component
tokland

回答:


302

React 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の完全なデモについては、ここをクリックしてください

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

}

クラスコンポーネント-Refコールバック

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年8月)。

文字列参照にはいくつかの問題があり、レガシーと見なされており、将来のリリースの1つで削除される可能性があります。[公式Reactドキュメント]

リソース1 リソース2

オプション:スムーススクロールアニメーション

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

refを子供に渡す

refは、反応コンポーネントではなくdom要素にアタッチする必要があります。したがって、子コンポーネントに渡す場合、prop refに名前を付けることはできません。

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

次に、refプロップをdom要素にアタッチします。

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

5
window.scrollTo(0, offsetTop)は、現在のブラウザー間でのサポートが改善された優れたオプションです
MoMo

1
あなたがあなたの例で一貫していることを確認することができます。myRefから始まり、domRefで終わり、tesNode?で終わります。それはかなり混乱しています
Louis Lecocq

4
事実の後は明らかですが、これはネイティブDOM要素に対してのみ機能し、Reactコンポーネントだけでは機能しないことを言及することが重要です。
jpunk11

1
@ jpunk11回答を更新しました。更新された回答は、子クラスコンポーネントにあるdom要素にスクロールする方法を説明しています。
Ben Carp

2
@SimonFranzen私の更新された回答-TLDR-クラスコンポーネントのケースを見てください。scrollToMyRefが呼び出されると、refをアタッチした子までスクロールします。メソッドを別の子コンポーネントに渡し、そこからトリガーできます。
Ben Carp、

55

これは私のために働いた

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

編集:私はコメントに基づいてこれを拡張したいと思いました。

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

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

1
これをどこに置くか
su_sundariya 2018年

ライフサイクルメソッドまたはコンストラクタ内
su_sundariya 2018年

1
魅力のように機能します。上記のどれも私にはうまくいきません、これは受け入れられるべき答えです!

1
私にとってはうまくいきました、「start」が「block」パラメーターのデフォルト値であることに注意してください。
Liron Lavi

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

更新:

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

2
これがより良い答えです。使用ReactDOM.findDomNode()することをお勧めします。Reactはコンポーネントを再レンダリングするため、IDで単純に取得したdivは、関数を呼び出すまでに存在しない可能性があります
良いアイデア

4
公式ドキュメントによると、使用は避けてくださいfindDOMNode。ほとんどの場合、DOMノードに参照をアタッチしてfindDOMNode、まったく使用しないようにすることができます。
Facyo Kouch

1
注文字列マッピングによりthis.refsを使用は推奨されていることを、次を参照してください。stackoverflow.com/questions/43873511/...
Himmet Avsar

1
注:のthis.myRef.current.scrollIntoView()代わりに使用する必要がありましたwindow.scrollTo(0, this.myRef)
Babbz77 2018年

14

findDOMNodeの使用は、最終的には廃止される予定です。

推奨される方法は、コールバック参照を使用することです。

github eslint


3
リンクされた資料の関連部分を含めてください。削除された場合に備えて、回答が役に立たないようにしてください。
totymedli 2018

12

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

私はあなたのコードを使用しようとしています。私は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年7月-専用フック/関数

専用のフック/関数は実装の詳細を隠すことができ、コンポーネントにシンプルなAPIを提供します。

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

完全なデモ

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

this.gate.offsetTopではなくe.offsetTopが必要な場合がありますが、this.gateを関数に渡してください。
KingOfHypocrites 2018

5

あなたは次のようなものを使うことができます componentDidUpdate

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

3
要素idを使用することは、反応には好ましくないと思います。仮想domの概念を破る
iamsaksham 2018年

ライフサイクルメソッドを使用すると、コードを実行するWHEN / WHEREまで到達できます。しかし、おそらく実際のコードのためにこの回答で見られる他の方法論を使用したいと思います
Dameo

3

簡単なシナリオがありました。ユーザーがマテリアルUIナビゲーションバーのメニュー項目をクリックしたときに、ページのセクションまでスクロールしたいと思います。refsを使用してすべてのコンポーネントを介してスレッド化することはできますが、コードが壊れやすくなるため、propsが複数のコンポーネントをプロップすることは嫌いです。

反応コンポーネントでバニラJSを使用したところ、問題なく機能することがわかりました。スクロールしたい要素にIDを配置し、ヘッダーコンポーネントにこれを実行しました。

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 UIコンポーネントでこれらのソリューションを機能させることができませんでした。彼らは持っていないように見えます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コンポーネントにスクロールする場合は、refをレンダリングされた要素に転送する必要があります。この記事では、問題についてさらに詳しく説明します


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

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


0

これをonclick関数内で使用して、idが「step2Div」であるdivまでスムーズにスクロールしました。

let offset = 100;
window.scrollTo({
    behavior: "smooth",
    top:
    document.getElementById("step2Div").getBoundingClientRect().top -
    document.body.getBoundingClientRect().top -
    offset
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.