如何在ReactJs+XMPP开发的聊天应用中让最新未读消息以粗体显示
未读最新消息加粗实现方案
1. Redux 层状态处理
首先调整消息存储结构和状态流转逻辑:
- 给每条消息新增
isUnread布尔字段,新接收的消息默认赋值为true - 在XMPP新消息监听回调中,触发Redux的新增消息action,把新消息写入store时自动标记为未读
- 新增「标记消息已读」的action,在用户进入对应会话、或滚动到消息列表最底部时触发,将对应消息的
isUnread改为false
2. 组件层渲染逻辑
在React消息列表组件中做判断渲染:
- 用
useSelector从Redux中拉取当前会话的消息列表 - 倒序遍历消息列表,找到第一条
isUnread为true的消息,即为最新的未读消息 - 渲染每条消息时,判断当前消息ID是否等于最新未读消息ID,匹配则添加加粗样式
3. 代码示例
Redux Slice 示例(基于Redux Toolkit)
import { createSlice } from '@reduxjs/toolkit' const chatSlice = createSlice({ name: 'chat', initialState: { // 多会话场景可按会话ID分组存储消息 messages: [] }, reducers: { addNewMessage: (state, action) => { // 新消息默认标记为未读 state.messages.push({...action.payload, isUnread: true}) }, markCurrentSessionRead: (state) => { // 将当前会话所有消息标记为已读 state.messages.forEach(msg => msg.isUnread = false) } } }) export const { addNewMessage, markCurrentSessionRead } = chatSlice.actions export default chatSlice.reducer
XMPP 新消息监听
// xmpp客户端实例监听新消息事件 xmppClient.on('message', (receivedMsg) => { // 解析消息内容后 dispatch 到Redux store.dispatch(addNewMessage({ id: receivedMsg.id, content: receivedMsg.body, senderId: receivedMsg.from, timestamp: Date.now() })) })
消息列表组件示例
import { useSelector, useDispatch } from 'react-redux' import { markCurrentSessionRead } from './chatSlice' const MessageList = () => { const dispatch = useDispatch() const messages = useSelector(state => state.chat.messages) // 获取最新未读消息ID const latestUnreadMsgId = messages.slice().reverse().find(msg => msg.isUnread)?.id // 监听滚动事件,滚动到底部时标记所有消息已读 const handleListScroll = (e) => { const isScrollToBottom = e.target.scrollHeight - e.target.scrollTop === e.target.clientHeight if (isScrollToBottom) dispatch(markCurrentSessionRead()) } return ( <div className="message-container" onScroll={handleListScroll}> {messages.map(msg => ( <div key={msg.id} className={`message-item ${msg.id === latestUnreadMsgId ? 'bold-unread' : ''}`} > {msg.content} </div> ))} </div> ) }
样式示例
.bold-unread { font-weight: 700; }
补充说明
如果需求是所有未读消息都加粗,不需要单独判断最新未读ID,直接在渲染时判断msg.isUnread为true时添加加粗样式即可。
内容的提问来源于stack exchange,提问作者Wani
相关产品推荐
相关产品推荐

