mls*_*712 8 javascript jsx reactjs
我的应用程序包含一个基本输入,用户可以在其中键入一条消息。然后将消息附加到所有其他消息的底部,就像聊天一样。当我向消息数组添加新的聊天消息时,我还想向下滚动到该消息。
每个 html 元素都有一个基于循环中的索引动态创建的 ref,该索引将它们打印出来。添加新消息的代码尝试在添加新消息后滚动到最新消息。
此代码仅在放置在 setTimeout 函数中时才有效。我不明白为什么会这样。
从数组中创建注释的代码
comments = this.state.item.notes.map((comment, i) => (
<div key={i} ref={i}>
<div className="comment-text">{comment.text}</div>
</div>
));
Run Code Online (Sandbox Code Playgroud)
添加新评论的按钮
<input type="text" value={this.state.textInput} onChange={this.commentChange} />
<div className="submit-button" onClick={() => this.addComment()}>Submit</div>
Run Code Online (Sandbox Code Playgroud)
添加评论功能
addComment = () => {
const value = this.state.textInput;
const comment = {
text: value,
ts: new Date(),
user: 'Test User',
};
const newComments = [...this.state.item.notes, comment];
const newState = { ...this.state.item, notes: newComments };
this.setState({ item: newState });
this.setState({ textInput: '' });
setTimeout(() => {
this.scrollToLatest();
}, 100);
}
scrollToLatest = () => {
const commentIndex = this.state.xrayModalData.notes.length - 1;
this.refs[commentIndex].scrollIntoView({ block: 'end', behavior: 'smooth' });
};
Run Code Online (Sandbox Code Playgroud)
如果我不在 setTimeout 中调用 scrollToLatest(),它就不起作用。它不会产生错误,它只是什么都不做。我的想法是它试图在状态完全设置之前运行,但我尝试向 setState 函数添加回调来运行它,但它也不起作用。
添加新的注释和引用将需要在组件更新生命周期中进行另一次渲染,并且您尝试在渲染之前访问引用(setTimeout 已解决)。您应该努力使用 React 组件生命周期方法。尝试在生命周期方法componentDidUpdate中调用scrollToLatest,该方法在渲染执行后调用。
虽然您肯定正确地认为设置状态是一个异步过程,但更新生命周期方法(例如,shouldComponentUpdate、render 和 componentDidUpdate)直到状态更新之后才会启动,并且您的 setState 回调可能会在组件更新之前被调用。实际上是通过渲染更新的。React文档可以对组件生命周期提供一些额外的说明。
最后,为了不在每次更新时调用你的滚动方法(仅在重要的更新上),你可以实现另一个生命周期方法 getSnapshotBeforeUpdate,它允许你比较之前的状态和当前状态,并将返回值传递给 componentDidUpdate 。
getSnapshotBeforeUpdate(prevProps, prevState) {
// If relevant portion or prevState and state not equal return a
// value, else return null
}
componentDidUpdate(prevProps, prevState, snapshot) {
// Check value of snapshot. If null, do not call your scroll
// function
}
Run Code Online (Sandbox Code Playgroud)