滚动到映射数组的最后一项

Scroll to the last item of a mapped array

我有一个 Message 组件,它在一个线程中显示所有消息(传入和传出)。

我希望最后 message/a 条新输入的 message/incoming 消息始终显示在对话的底部。有点像所有 chats/messaging 应用程序所做的。

这是我的代码:

import React, { useRef } from "react";

const dummy = useRef();

...

dummy?.current?.scrollIntoView(true, {
    behaviour: "auto",
});

... 

<div className="">
  <Paper
    elevation={0}
    sx={{
      backgroundColor: "#fafafa",
      maxHeight: 200,
      overflow: "auto",
    }}
  >
    {messages.map((message, idx) => (
      <div key={idx} ref={dummy}>
        <Message message={message} name={name} />
      </div>
    ))}
    {/* I tried this also
    <div ref={dummy}></div> */}
  </Paper>
</div>

我希望当我单击 conversation/thread 时,所有可以放入带有 maxHeight: 200 的父 div 的消息,最后一条消息显示在底部。目前,整个页面滚动到底部,而不仅仅是线程中的消息。页面应保持静止。

我该怎么做?

问题是您将 ref 传递给呈现 Message 组件的 div 元素。我建议你在聊天结束时使用虚拟 div,然后在你的组件更新时滚动到它。

return (
    <div
      className="messagesWrapper"
      style={{ background: "white", border: "2px red solid" }}
    >
      {messages.map((message) => (
        <span key={message}>{message}</span>
      ))}
      <div ref={dummy} />
    </div>
  );

ref 元素在 useEffect 中更新。

const dummy = useRef(null);
useEffect(() => {
  dummy.current.scrollIntoView({ behavior: "smooth" });
}, [messages]);

附上一张sandbox供参考。

所以您可以做的是创建一个 useRef,然后将其初始化为 null

然后当您在数组上映射以呈现对象时,运行 一个函数来检查它是否是数组中的最后一项

如果它是数组中的最后一个对象,则将 ref 附加到它

然后使用依赖数组中的 ref 进行 useEffect

如果 useRef 设置了一个新值,从 .map,在你的 useEffect 中,有一个 scrollTo 行为,平滑的,滚动到它的功能

我认为这会起作用:

React.useEffect(() => {
    dummy.current.scrollTop = dummy.current.scrollHeight
})