Skip to main content

概述

使用 Zustand 进行轻量级状态管理。

Store 结构

store
poisson.ts
auth.ts
feed.ts
Thread 数据和用户 profile 数据通过 TanStack Query 从服务端获取,不使用 Zustand store。

Poisson Store

usePoissonStore(来自 store/poisson.ts)管理 Generator 相关状态,使用嵌套 map 模式 poissonMap[threadId] 存储每个 thread 的独立状态。
// store/poisson.ts
type EditMode = "chat" | "upscale" | "filter" | "adjust" | "crop" | "chooseFilter"
  | "inpaint" | "expand" | "replaceBg" | "eraser" | "mask" | "video"
  | "generateMusic" | "generateInstrumental" | "addVocals" | "generateImage";

type KiraModel = "lite" | "nova" | "crazy" | "ultra";

interface PoissonState {
  // 模型选择(顶层,通过 persist 中间件持久化到 localStorage)
  model: KiraModel;

  // 嵌套 map,按 threadId 隔离状态
  poissonMap: Record<string, {
    currentImage: Image;
    currentVersionId: string;
    versions: Version[];
    messages: UIMessage[];
    tempMessages: UIMessage[];
    executingTool: { toolName: string; args: object } | null;
    chatStatus: ChatStatus;
    inputState: InputState;
    errorInfo: ToolError[] | null;
    editMode: EditMode;
    editModeData?: any;
    isReceivingMessage: boolean;
    isReceivingVersions: boolean;
    currentSelectVideo?: Video;
    currentSelectAudio?: Audio;
    currentSelectMediaType: "image" | "video" | "audio";
  }>;

  // Actions(均需传入 threadId)
  setCurrentImage: (threadId: string, image: Image) => void;
  setEditMode: (threadId: string, mode: EditMode) => void;
}

export const usePoissonStore = create<PoissonState>(
  persist(/* ... */, { name: 'poisson-store', partialize: (state) => ({ model: state.model }) })
);
Store 使用 Zustand 的 persist 中间件,通过 localStorage 持久化 model 字段。

Auth Store

useAuthStore(来自 store/auth.ts)仅管理认证状态。用户 profile 数据通过 TanStack Query 获取。
// store/auth.ts
interface AuthState {
  isAuth: boolean;
  login: () => void;
  logout: () => void;
}

Feed State Store

useFeedStateStore(来自 store/feed.ts)管理 Feed 相关状态。
// store/feed.ts
interface FeedState {
  deletedFeed: string[];             // 已删除的 feed ID 列表

  localDeleteFeed: (feedId: string) => void;    // 本地标记删除
  localRecoverFeed: (feedId: string) => void;   // 本地恢复
  getDeletedFeed: (feedId: string) => boolean;    // 判断是否已删除
}

使用方式

// 组件中使用
function ImagePanel({ threadId }: { threadId: string }) {
  const currentImage = usePoissonStore(
    (state) => state.poissonMap[threadId]?.currentImage
  );

  return <img src={currentImage?.url} />;
}

最佳实践

  1. 每个功能模块一个 Store
  2. 状态和 Actions 定义在同一个 Store 中
  3. 使用选择器避免不必要的重渲染