You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Zustand Instagram克隆应用:重置全局帖子计数状态问题

解决Zustand全局状态帖子计数异常与加载缓慢问题

问题背景

开发React+Zustand的Instagram克隆应用时,用addPost统计用户帖子数量展示在个人主页。deletePost功能正常,但全局状态残留测试时的旧数据——实际用户有3条帖子,却显示5条。尝试在getUserPosts钩子中添加重置帖子为空数组的操作后,个人主页加载时间变长。

问题分析

  1. deletePost逻辑错误:userProfile.posts存储的是帖子ID的数组,而非完整的帖子对象,但代码中用post.id !== id进行过滤,导致无法正确移除已删除的帖子ID,旧数据残留。
  2. 状态不同步:本地状态的帖子ID数组未与Firestore数据完全同步,测试阶段的旧操作记录留在了全局状态中。
  3. 加载优化问题:提前调用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ć

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:41:02