我正在使用 Firebase Firestore 在 Next.js 应用程序中开发聊天功能,但遇到两个问题:
// UserChatWrapper.tsx
const UserChatWrapper = ({ user, allMessages, sendMessageAction }: Props) => {
const formRef = useRef<HTMLFormElement>(null);
const chatsAutoScroll = useRef<HTMLDivElement>(null);
const [message, setMessage] = useState("");
const [error, setError] = useState<string>("");
const [optimisticMessages, addOptimisticMessage] = useOptimistic(
allMessages.messages,
(state: Message[], newMessage: Message) => [...state, newMessage]
);
return (
<>
<form
ref={formRef}
onSubmit={() => setMessage("")}
action={async (e) => {
if (!message) return;
addOptimisticMessage({
id: v4(),
type: "text",
deleted: false,
sender: {
username: user.displayName || "User",
uid: user.uid,
},
recipient: "admin",
content: { text: message },
timeStamp: new Date(),
edited: false,
read_receipt: {
delivery_status: "not_sent",
status: false,
},
});
setMessage("");
if (chatsAutoScroll.current) {
chatsAutoScroll.current.scrollTop =
chatsAutoScroll.current.scrollHeight;
}
formRef?.current?.reset();
sendMessageAction(e).then((res: { error: string }) => {
if (res?.error) setError(res?.error);
});
}}
></form>
{error && error}
</>
);
};
export default UserChatWrapper;
// page.tsx
const UserChatWrapper = dynamic(
() => import("@/components/chat/ChatWrapper"),
{ ssr: false }
);
type Props = {
params: { chatId: string };
};
const UserChatScreen = ({ params }: Props) => {
const [messages, setMessages] = useState<Conversation>();
const user = Cookies.get("user") ? JSON.parse(Cookies.get("user")) : null;
const router = useRouter();
useEffect(() => {
if (!user) redirect("/sell");
});
useEffect(() => {
const unsubscribe = onSnapshot(
doc(db, "Messages", params.chatId),
(doc) => {
if (!doc.exists()) router.push("/sell");
setMessages(doc.data() as Conversation);
}
);
return () => unsubscribe();
}, [params.chatId, router]);
const sendMessageAction = sendUserMessage.bind(
null,
{ timeStamp: new Date() },
params.chatId
);
return (
<>
{messages ? (
<UserChatWrapper
user={user}
allMessages={messages}
sendMessageAction={sendMessageAction}
/>
) : (
<div className="text-center p-8">Please wait...</div>
)}
</>
);
};
export default UserChatScreen;
重复消息问题:
发送消息时,在更新之前会短暂地显示为重复消息。
如何防止出现重复消息并确保更新无缝?
性能问题:
我注意到当前聊天设置存在潜在的性能问题。
我可以实施任何具体的改进或最佳实践来优化聊天功能的性能吗?
整体聊天设置:
使用 React 和 Firebase 设置实时聊天功能有哪些推荐的最佳实践?
关于如何构建组件和管理状态以获得更流畅的用户体验有什么建议吗?
我尝试删除 useOptimistic 并简单地使用它,但明显的缺点是消息需要一段时间才能出现,我也尝试使用 startTransition 并面临同样的问题。
回答“重复消息问题”。
由于您使用
onSnapshot
,Firestore SDK 在将新数据发送到服务器之前已经使用新数据调用您的本地回调。据我所知,你的 addOptimisticMessage
也有同样的作用,但这不是必需的。您可以删除 addOptimisticMessage
并依靠 Firebase 为您处理乐观的本地更新。