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
相关产品推荐
相关产品推荐

