211 votes

Comment faire défiler vers le bas pour réagir?

Je souhaite créer un système de discussion en ligne et faire défiler automatiquement le texte vers le bas lors de l'ouverture de la fenêtre et de l'arrivée de nouveaux messages. Comment faire défiler automatiquement le contenu d'un conteneur dans React?

319voto

kermit666 Points 1730

Comme Tushar l'a mentionné, vous pouvez garder une div factice au bas de votre conversation:

 render () {
  return (
    <div>
      <div className="MessageContainer" >
        <div className="MessagesList">
          {this.renderMessages()}
        </div>
        <div style={{ float:"left", clear: "both" }}
             ref={(el) => { this.messagesEnd = el; }}>
        </div>
      </div>
    </div>
  );
}
 

puis faites défiler jusqu'à ce que votre composant soit mis à jour (c.-à-d. l'état mis à jour à mesure que de nouveaux messages sont ajoutés):

 scrollToBottom = () => {
  this.messagesEnd.scrollIntoView({ behavior: "smooth" });
}

componentDidMount() {
  this.scrollToBottom();
}

componentDidUpdate() {
  this.scrollToBottom();
}
 

J'utilise la méthode standard Element.scrollIntoView ici.

61voto

tgdn Points 1042

Ne pas utiliser findDOMNode

 class MyComponent extends Component {
  componentDidMount() {
    this.scrollToBottom();
  }

  componentDidUpdate() {
    this.scrollToBottom();
  }

  scrollToBottom() {
    this.el.scrollIntoView({ behavior: 'smooth' });
  }

  render() {
    return <div ref={el => { this.el = el; }} />
  }
}
 

32voto

jk2K Points 1920

Grâce à @enlitement

nous devrions éviter d'utiliser des findDOMNode, on peut utiliser refs pour garder la trace des composants

render() {
  ...

  return (
    <div>
      <div
        className="MessageList"
        ref={(div) => {
          this.messageList = div;
        }}
      >
        { messageListContent }
      </div>
    </div>
  );
}



scrollToBottom() {
  const scrollHeight = this.messageList.scrollHeight;
  const height = this.messageList.clientHeight;
  const maxScrollTop = scrollHeight - height;
  this.messageList.scrollTop = maxScrollTop > 0 ? maxScrollTop : 0;
}

componentDidUpdate() {
  this.scrollToBottom();
}

référence:

7voto

Tushar Agarwal Points 182

J'ai créé un élément vide à la fin des messages et j'ai fait défiler cet élément. Pas besoin de garder une trace des arbitres.

7voto

Marcin Rapacz Points 408
  1. Référencez votre conteneur de messages.

     <div ref={(el) => { this.messagesContainer = el; }}> YOUR MESSAGES </div>
     
  2. Trouvez votre conteneur de messages et de faire sa scrollTop attribuent égale scrollHeight :

     scrollToBottom = () => {
        const messagesContainer = ReactDOM.findDOMNode(this.messagesContainer);
        messagesContainer.scrollTop = messagesContainer.scrollHeight;
    };
     
  3. Évoquez la méthode ci-dessus sur componentDidMount et componentDidUpdate .

     componentDidMount() {
         this.scrollToBottom();
    }
    
    componentDidUpdate() {
         this.scrollToBottom();
    }
     

Voici comment je l'utilise dans mon code:

  export default class StoryView extends Component {

    constructor(props) {
        super(props);
        this.scrollToBottom = this.scrollToBottom.bind(this);
    }

    scrollToBottom = () => {
        const messagesContainer = ReactDOM.findDOMNode(this.messagesContainer);
        messagesContainer.scrollTop = messagesContainer.scrollHeight;
    };

    componentDidMount() {
        this.scrollToBottom();
    }

    componentDidUpdate() {
        this.scrollToBottom();
    }

    render() {
        return (
            <div>
                <Grid className="storyView">
                    <Row>
                        <div className="codeView">
                            <Col md={8} mdOffset={2}>
                                <div ref={(el) => { this.messagesContainer = el; }} 
                                     className="chat">
                                    {
                                        this.props.messages.map(function (message, i) {
                                            return (
                                                <div key={i}>
                                                    <div className="bubble" >
                                                        {message.body}
                                                    </div>
                                                </div>
                                            );
                                        }, this)
                                    }
                                </div>
                            </Col>
                        </div>
                    </Row>
                </Grid>
            </div>
        );
    }
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X