React+Zustand Instagram克隆应用:重置全局帖子计数状态问题
解决Zustand全局状态帖子计数异常与加载缓慢问题
问题背景
开发React+Zustand的Instagram克隆应用时,用addPost统计用户帖子数量展示在个人主页。deletePost功能正常,但全局状态残留测试时的旧数据——实际用户有3条帖子,却显示5条。尝试在getUserPosts钩子中添加重置帖子为空数组的操作后,个人主页加载时间变长。
问题分析
- deletePost逻辑错误:
userProfile.posts存储的是帖子ID的数组,而非完整的帖子对象,但代码中用post.id !== id进行过滤,导致无法正确移除已删除的帖子ID,旧数据残留。 - 状态不同步:本地状态的帖子ID数组未与Firestore数据完全同步,测试阶段的旧操作记录留在了全局状态中。
- 加载优化问题:提前调用
setPosts([])会触发额外的状态更新和组件重渲染,导致加载时间变长。
解决方案
1. 修复deletePost过滤逻辑
修改useUserProfileStore中的deletePost方法,针对帖子ID数组做正确过滤:
import { create } from "zustand" const useUserProfileStore = create((set) => ({ userProfile: null, setUserProfile: (userProfile) => set({ userProfile }), addPost: (post) => set(state => ({ userProfile: { ...state.userProfile, posts: [post.id, ...state.userProfile.posts] } })), deletePost: (id) => set((state) => ({ userProfile: { ...state.userProfile, // 修复:直接对比帖子ID,而非对象属性 posts: state.userProfile.posts.filter(postId => postId !== id) } })), // 新增:同步帖子ID数组的方法,确保和Firestore数据一致 syncUserPosts: (postIds) => set(state => ({ userProfile: { ...state.userProfile, posts: postIds } })) })) export default useUserProfileStore;
2. 同步全局状态与Firestore数据
修改useGetUserPosts钩子,在获取Firestore数据后,同步更新userProfile中的帖子ID数组,彻底清除残留数据,同时移除不必要的空数组重置操作:
import { useEffect, useState } from 'react'; import useShowToast from './useShowToast' import usePostStore from '../store/postStore'; import useUserProfileStore from '../store/userProfileStore'; import { collection, getDocs, query, where } from 'firebase/firestore'; import { firestore } from '../Firebase/firebase'; const useGetUserPosts = () => { const showToast = useShowToast(); const [isLoading, setIsLoading] = useState(true); const { setPosts } = usePostStore(); const userProfile = useUserProfileStore(state => state.userProfile); const syncUserPosts = useUserProfileStore(state => state.syncUserPosts); useEffect(() => { const getPosts = async () => { if (!userProfile) return; setIsLoading(true); try { const q = query(collection(firestore, "posts"), where("createdBy", "==", userProfile.uid)); const querySnapshot = await getDocs(q); const posts = []; const postIds = []; querySnapshot.forEach((doc) => { const postData = { ...doc.data(), id: doc.id }; posts.push(postData); postIds.push(doc.id); }); posts.sort((a, b) => b.createdAt - a.createdAt); setPosts(posts); // 同步帖子ID数组到userProfileStore,确保计数准确 syncUserPosts(postIds); } catch (error) { showToast("Error", error.message, "error"); setPosts([]); syncUserPosts([]); } finally { setIsLoading(false); } }; getPosts(); }, [setPosts, userProfile, showToast, syncUserPosts]); // 直接从store获取帖子列表,避免依赖本地state return { isLoading, posts: usePostStore(state => state.posts) }; }; export default useGetUserPosts;
3. 关键优化点说明
- 修复
deletePost的过滤逻辑后,删除操作能正确移除对应帖子ID,不会留下残留数据。 - 新增
syncUserPosts方法,每次从Firestore拉取数据后同步更新全局状态的帖子ID数组,确保本地状态与数据库完全一致。 - 移除
setPosts([])的提前调用,避免不必要的重渲染,缩短加载时间。
内容的提问来源于stack exchange,提问作者Adrian Palčić
相关产品推荐
相关产品推荐

