Working on a nextjs app using typescript w/ a firestore backend.
I currently am using my own useContext hook to make globally available a firestore user object, an array of 'business entity IDs' (strings) that the user is authorized to view, as well as an array of objects containing each biz's document data.
Because a user can be a member of multiple business entities, I'd like to be able to have them toggle between a 'current business' object whose document ID would be used to pass into further queries as well as document add / update functions.
I'm just not sure how to go about trigger the setting and switching of this 'current biz' id.
I'm assuming I'd want to somehow set the value in another usecontext hook so that the value is globally available to use around the app?
Below is my current custom context hooks doc
please let me know if you'd need to see any more data
import { auth, firestore } from "../lib/firebase";
import { useContext, useEffect, useState } from "react";
import { useAuthState } from "react-firebase-hooks/auth";
import {
doc,
onSnapshot,
collection,
query,
where,
getDocs,
} from "firebase/firestore";
import { BizContext } from "./context";
//types
// Custom hook to read auth record and user profile doc
export function useUserData() {
const [user, loading, error] = useAuthState(auth);
const [username, setUsername] = useState(null);
useEffect(() => {
// turn off realtime subscription
let unsubscribe;
//this actively listens to a the users collection
if (user) {
const userDocRef = doc(firestore, "users", user.uid);
unsubscribe = onSnapshot(userDocRef, (doc) => {
setUsername(doc.data()?.username);
});
} else {
setUsername(null);
}
return unsubscribe;
}, [user]);
return { user, username };
}
export function useBelongsTo() {
const [user] = useAuthState(auth);
const [belongsTo, setBelongsTo] = useState<[]>([]);
const [bizInfo, setBizInfo] = useState<[]>([]);
useEffect(() => {
let unsubscribe;
if (user) {
const bizColRef = collection(firestore, "businesses");
const q = query(bizColRef, where("admins", "array-contains", user.uid));
unsubscribe = onSnapshot(q, (querySnapshot) => {
let bizId: [] = [];
let bizInfo: [] = [];
querySnapshot.forEach((doc) => {
bizId.push(doc.id);
bizInfo.push(doc.data());
});
setBelongsTo(bizId);
setBizInfo(bizInfo);
});
} else {
setBelongsTo([]);
console.log("no businesses, no user");
}
return unsubscribe;
}, [user]);
return { belongsTo, bizInfo };
}
_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 } from "../lib/context";
import { useBelongsTo, useUserData } from "../lib/hooks";
import Layout from "../components/layout/Layout";
function MyApp({ Component, pageProps }: AppProps) {
const userData = useUserData();
const bizData = useBelongsTo();
return (
<ChakraProvider theme={customTheme}>
<UserContext.Provider value={userData}>
<BizContext.Provider value={bizData}>
<Layout>
<Component {...pageProps} />
<Toaster />
</Layout>
</BizContext.Provider>
</UserContext.Provider>
</ChakraProvider>
);
}
export default MyApp;
context.tsx
import React from "react";
export const UserContext = React.createContext({});
export const BizContext = React.createContext({});