[Rreact]:如果需要,使用Ref滚动IntoView不同线程的最后一条消息



我遇到了一个问题,在我的应用程序中,用户可以加载不同的消息线程,如果该线程的长度超过了查看区域(即,需要滚动条来查看底部消息(,那么我想自动滚动到最后一条消息。

使用useRef,我在地图后面标记一个地方,如下所示:

currentList.map(elem => ( <div>{elem}</div>) )
<div ref={messagesRef} /> // <------Here

我的问题是,通过使用useRef.current字段,我的消息线程选择总是落后一步,因为ref在装载后从null更新,因此落后于我主动选择的内容。也正因为如此,我不得不强制进行检查,以确保我没有像这样试图对null ref做任何事情:

useEffect(() => {
if (messagesRef.current) { // < -- make sure we're not null
scrollToBottom();
}
}, [messagesRef]);

scrollToBottom方法是这样的:

const scrollToBottom = () => {
messagesRef.current.scrollIntoView({
behavior: "smooth",
block: "nearest" // <-- only scroll this div, not the parent as well
});
};

正如我之前所说,我的目标是让用户选择不同的线程,对于任何需要滚动到底部的线程,我都会为它们这样做。然而,当他们选择一个线程时,当注销引用messagesRef.current的状态时,它会在所选线程后面呈现一个线程。我通过输出messagesRef.current.parentNode.offsetHeight的结果来检查这一点。

每个不需要滚动的线程的offsetHeight都小于我的消息窗口高度(在我的情况下是500(。而那个确实需要滚动的,比我的窗口高度还大。

当当前值没有随着我的选择而更新时,试图依赖这个useRef非常令人沮丧。

虽然我无法解决useRef比我的选择落后一步的问题,但我能够解决我的最终问题并产生我想要的结果;如果需要,自动滚动到最后一条消息。

虽然useRef.current落后了,但没有落后的是我的消息线程的状态。所以,当我需要滚动时,用它来检查,问题就解决了。

useEffect(() => {
// be sure we need to scroll, length of 2 equates to the visual size of the message box
if (currentList.length > 2) { // <-- more than 2, we've grown outside the window 
scrollToBottom();
}
}, [currentList]); // <- update dependency array to state, not the Ref

这是我的最终工作版本。你可以看到线程一开始是空的,然后当你在按钮上选择时,如果需要,线程将滚动到底部。

https://codesandbox.io/s/userefissue-v86kq

希望这能帮助到未来的人,如果有什么关于如何让我的裁判了解我目前的选择的建议,我很乐意听到解决方案!

最新更新