React聊天组件发新消息时滚动条无法自动滚动到底部问题
问题详情
在基于React开发的即时聊天界面中存在两类滚动条交互异常:
- 发送长段落内容的新消息时,聊天feed区域滚动条无法自动向下跟踪到最新消息位置。预期交互逻辑为:用户发送新消息时,滚动条应自动滚动至聊天区域最底部,新消息持续发送时保持在底部位置。
- 已实现的基础
scrollIntoView滚动逻辑存在额外缺陷:用户手动滚动到聊天区域顶部查看历史消息时,组件触发重渲染后会强制将视图跳转回最后一条消息的顶部位置,打断用户查看历史消息的操作,不符合交互预期。
ChatBubble单条消息组件实现代码
<div ref={forwardedRef} className={containerClasses} data-bubble-index={index} > {!myMsg && bubble.fromDisplayName && ( <div className="mr-2"> <AvatarPhoto name={bubble.fromDisplayName} size="sm" src={bubbleParticipant.avatarUrl} /> </div> )} <div className={bubbleContainerClasses}> {!sameFrom && !myMsg && ( <span className="text-sm text-gray-400"> {myMsg ? 'me' : bubble.fromDisplayName}{' '} {bubbleParticipant?.roleLabel && `(${bubbleParticipant?.roleLabel})`} </span> )} <div className="w-full"> {bubble.message?.match(url_pattern) ? ( <span className={bubbleClasses} dangerouslySetInnerHTML={{ __html: replaceUrlsWithAnchors(bubble.message), }} /> ) : ( <span className={bubbleClasses}>{bubble.message}</span> )} </div> </div> </div>
父容器实现代码
<div className="flex flex-col justify-between h-full" data-cy="chatThread"> <div className="sticky top-0 bg-primaryBg"> <SidePanelHeader onDismiss={handleChatToggle} alignChildren="left"> <button className="flex items-center pl-2" onClick={showActiveChats}> <span className="mr-1"> <Icon svg={LeftArrow} size={10} color="accentText" /> </span> Back to All chats </button> </SidePanelHeader> <ChatGroups chatId={chatId} isMyParty={isMyParty} isTeamMeeting={meeting?.type?.key === 'team-meeting'} chatGroupParties={chatGroupParties} dmParticipant={dmParticipant ? dmParticipant[0] : undefined} /> </div> </div>
聊天Feed区域实现代码
{/* Chat Feed*/} <div className={classNames('flex flex-auto flex-col overflow-y-auto p-3', { 'bg-red-100': !isMyParty && meeting?.type?.key !== 'team-meeting', })} data-cy="chatThread-feed" > {mergedMessagesAndParticipantsInThread().map((chatBubble, index) => ( <ChatBubble participants={allParticipantsFlat} prevBubble={getMessages()[index - 1]} bubble={chatBubble} index={index} key={chatBubble.ts} ref={scrollToRef} /> ))} </div>
问题表现截图

现有滚动逻辑实现代码
const scrollToRef = (node: HTMLElement | null) => { if (node !== null) { const refIndex = Number(node?.dataset?.bubbleIndex) + 1; const ref = document.querySelector(`[data-bubble-index="${refIndex}"]`); if (ref && ref.getBoundingClientRect().top > 0) { ref.scrollIntoView({ behavior: 'auto', block: 'start', }); } } }
内容的提问来源于stack exchange,提问作者Luis Pozo
相关产品推荐
相关产品推荐

