web-dev-qa-db-fra.com

ReactJS comment faire défiler un élément

J'ai un widget de discussion qui affiche une série de messages à chaque défilement. Le problème auquel je suis confronté est que le curseur reste en haut du chargement des messages. Je souhaite qu'il se concentre sur le dernier élément d'index du tableau précédent. J'ai compris que je pouvais créer des références dynamiques en passant par l'index, mais que je devais également savoir quel type de fonction de défilement utiliser pour atteindre cet objectif.

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

  render() {

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

React 16.8 +, composant fonctionnel

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

Cliquez ici pour une démonstration complète sur StackBlits

React 16.3 +, composant de classe

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. 

}

Composant de classe - Rappel de référence

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

N'utilisez pas les références de chaîne.

Les références de chaîne nuisent aux performances, ne sont pas composables et sont en voie de disparition (août 2018).

les références de chaîne ont quelques problèmes, sont considérées comme héritées et sont susceptibles d'être supprimées dans l'une des prochaines versions. [Documentation officielle React]

ressource1ressource2

Facultatif: Lisser l'animation de défilement

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

Passer ref à un enfant

Nous voulons que la référence soit attachée à un élément dom, pas à un composant de réaction. Ainsi, lorsque vous le transmettez à un composant enfant, nous ne pouvons pas nommer le prop prop.

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

Ensuite, fixez l’appui sur un élément de dom.

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

Trouvez simplement la position supérieure de l'élément que vous avez déjà déterminé https: //www.w3schools.com/Jsref/prop_element_offsettop.asp puis faites défiler jusqu'à cette position via scrollTo méthode https: //www.w3schools.com/Jsref/met_win_scrollto.asp

Quelque chose comme ça devrait marcher:

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

UPDATE:

depuis Réagissez v16.3 la React.createRef() est préférée

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>)
}
33
Roman Maksimov

cela a fonctionné pour moi

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

L'utilisation de findDOMNode sera éventuellement obsolète.

La méthode préférée consiste à utiliser des références de rappel.

github eslint

14
sww314

Vous pouvez également utiliser la méthode scrollIntoView pour accéder à un élément donné.

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

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

Je suis peut-être en retard à la fête, mais j’essayais d’appliquer correctement les références dynamiques à mon projet et toutes les réponses que j’ai trouvées jusqu’à ce que je sache ne sont pas satisfaisantes à mon goût, alors j’ai trouvé une solution qui, à mon avis, est simple et utilise la manière native et recommandée de réagir pour créer la réf.

parfois, vous constatez que la façon dont la documentation est écrite suppose que vous avez un nombre connu de vues et que, dans la plupart des cas, ce nombre est inconnu. Vous avez donc besoin d'un moyen de résoudre le problème. Créez des références dynamiques avec le nombre inconnu de vues dont vous avez besoin. montrer dans la classe

donc la solution la plus simple que je pouvais penser et travaillait sans faille était de faire comme suit

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

de cette façon, le parchemin ira à la rangée que vous cherchez.

acclamations et espère que cela aide les autres

7
Miguel Sedek

Vous pouvez essayer de cette façon:

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

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

Vous pouvez maintenant utiliser useRef à partir de l’API de hook réactif

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

déclaration

let myRef = useRef()

composant

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

Utilisation

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

Vous pouvez utiliser quelque chose comme componentDidUpdate

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

Ce qui a fonctionné pour moi:

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
Artur Barseghyan

Utilisez la composition de fonction pour masquer les détails de l'implémentation

React 16.8 + Composant fonctionnel

useScroll hook

Le crochet useScroll suivant masque les détails de l’implémentation dom et fournit une API simple.

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

  return [executeScroll, htmlElRef]
}

Ensuite, vous pouvez facilement faire défiler vos composants fonctionnels.

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

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

}

Cliquez ici pour une démo complète sur StackBlitz

Réagir 16.3 + composant de classe

useizeScroll

La fonction de composition pourrait également être utilisée dans les composants de classe.

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

  return {executeScroll, htmlElRef}
}

Puis utilisez-le dans n'importe quel composant de classe

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

Cliquez ici pour une démo complète sur StackBlitz

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

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