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

Next.js+Firestore项目中基于useContext实现当前业务实体切换方案问询

实现多业务实体切换功能方案

1. 新增当前业务上下文

首先扩展context.tsx,添加管理当前业务ID的上下文并明确TypeScript类型:

import React from "react";

// 用户上下文类型
type UserContextType = {
  user: any;
  username: string | null;
};

// 业务列表上下文类型
type BizContextType = {
  belongsTo: string[];
  bizInfo: any[];
};

// 当前业务上下文类型
type CurrentBizContextType = {
  currentBizId: string | null;
  setCurrentBizId: (id: string | null) => void;
};

export const UserContext = React.createContext<UserContextType>({
  user: null,
  username: null,
});

export const BizContext = React.createContext<BizContextType>({
  belongsTo: [],
  bizInfo: [],
});

export const CurrentBizContext = React.createContext<CurrentBizContextType>({
  currentBizId: null,
  setCurrentBizId: () => {},
});

2. 在_app.tsx中管理当前业务状态

修改_app.tsx,添加当前业务的状态管理,并通过上下文提供全局访问:

import "../styles/globals.css";
import type { AppProps } from "next/app";
import { ChakraProvider } from "@chakra-ui/react";
import customTheme from "../extendTheme";
import { Toaster } from "react-hot-toast";
import { BizContext, UserContext, CurrentBizContext } from "../lib/context";
import { useBelongsTo, useUserData } from "../lib/hooks";
import { useState, useEffect } from "react";

import Layout from "../components/layout/Layout";

function MyApp({ Component, pageProps }: AppProps) {
  const userData = useUserData();
  const { belongsTo, bizInfo } = useBelongsTo();
  const [currentBizId, setCurrentBizId] = useState<string | null>(null);

  // 初始化:用户加载后自动设置第一个业务为当前业务
  useEffect(() => {
    if (belongsTo.length > 0 && !currentBizId) {
      setCurrentBizId(belongsTo[0]);
    }
  }, [belongsTo, currentBizId]);

  return (
    <ChakraProvider theme={customTheme}>
      <UserContext.Provider value={userData}>
        <BizContext.Provider value={{ belongsTo, bizInfo }}>
          <CurrentBizContext.Provider value={{ currentBizId, setCurrentBizId }}>
            <Layout>
              <Component {...pageProps} />
              <Toaster />
            </Layout>
          </CurrentBizContext.Provider>
        </BizContext.Provider>
      </UserContext.Provider>
    </ChakraProvider>
  );
}

export default MyApp;

3. 实现业务切换组件

创建BizSelector组件用于切换当前业务:

import { useContext } from "react";
import { BizContext, CurrentBizContext } from "../lib/context";
import { Select, Box } from "@chakra-ui/react";

export default function BizSelector() {
  const { belongsTo, bizInfo } = useContext(BizContext);
  const { currentBizId, setCurrentBizId } = useContext(CurrentBizContext);

  // 匹配业务ID和名称(假设bizInfo包含name字段)
  const bizOptions = belongsTo.map((id) => {
    const biz = bizInfo.find(item => item.id === id);
    return {
      value: id,
      label: biz?.name || id,
    };
  });

  if (belongsTo.length === 0) return null;

  return (
    <Box ml={4}>
      <Select
        value={currentBizId}
        onChange={(e) => setCurrentBizId(e.target.value)}
        placeholder="选择业务"
      >
        {bizOptions.map(opt => (
          <option key={opt.value} value={opt.value}>
            {opt.label}
          </option>
        ))}
      </Select>
    </Box>
  );
}

4. 在业务组件中使用当前业务ID

在需要查询/修改业务文档的组件中,通过上下文获取当前业务ID:

import { useContext, useEffect, useState } from "react";
import { CurrentBizContext } from "../lib/context";
import { firestore } from "../lib/firebase";
import { collection, query, where, onSnapshot } from "firebase/firestore";

export function useBizDocuments() {
  const { currentBizId } = useContext(CurrentBizContext);
  const [documents, setDocuments] = useState<any[]>([]);

  useEffect(() => {
    if (!currentBizId) return;

    const q = query(
      collection(firestore, "biz-documents"),
      where("bizId", "==", currentBizId)
    );

    const unsubscribe = onSnapshot(q, (snapshot) => {
      const docs = snapshot.docs.map(doc => ({
        id: doc.id,
        ...doc.data(),
      }));
      setDocuments(docs);
    });

    return unsubscribe;
  }, [currentBizId]);

  return { documents };
}

补充优化

  • 修改useBelongsTo钩子,把业务ID合并到bizInfo中,方便后续匹配:
    querySnapshot.forEach((doc) => {
      bizId.push(doc.id);
      bizInfo.push({ id: doc.id, ...doc.data() }); // 合并ID到业务信息
    });
    
  • 将BizSelector组件放入全局布局(如Layout的导航栏),实现全局可切换。

内容的提问来源于stack exchange,提问作者lostlostlost

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 08:54:23