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?
Réponses
Trop de publicités?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.
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; }} />
}
}
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:
-
Référencez votre conteneur de messages.
<div ref={(el) => { this.messagesContainer = el; }}> YOUR MESSAGES </div>
-
Trouvez votre conteneur de messages et de faire sa
scrollTop
attribuent égalescrollHeight
:scrollToBottom = () => { const messagesContainer = ReactDOM.findDOMNode(this.messagesContainer); messagesContainer.scrollTop = messagesContainer.scrollHeight; };
-
Évoquez la méthode ci-dessus sur
componentDidMount
etcomponentDidUpdate
.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>
);
}
}