React Context API+Firebase:解决未登录时创建空用户文档问题
解决方案:避免未登录时创建空用户文档
不用拆分回两个Provider,只需要在Firestore相关逻辑里增加address存在性判断,就能解决问题,具体改法如下:
关键改动点
- 只有当
address不为null时,才发起Firestore查询,否则跳过查询 - 创建用户文档前,先确认
address存在,避免写入null值 - 调整依赖项和加载状态的逻辑,确保状态同步
修改后的完整代码
const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => { const [signer, setSigner] = useState<ethers.Signer | null>(null); const [address, setAddress] = useState<string | null>(null); const [balance, setBalance] = useState<string | null>(null); // 只有address存在时才执行查询,否则返回空状态 const [userDoc, dbLoading] = address ? useCollection( query( collection(firestore, "users"), where("walletAddress", "==", address) ) ) : [null, false]; const [isLoading, setIsLoading] = useState<boolean>(true); const [isConnected, setIsConnected] = useState<boolean>(false); useEffect(() => { // 新增address存在的判断,避免写入null if (address && !dbLoading && userDoc?.empty) { addDoc(collection(firestore, "users"), { walletAddress: address, }); } setIsLoading(false); }, [dbLoading, address]); // 把address加入依赖项,确保地址变化时重新判断 const connect = () => { setIsLoading(true); provider .listAccounts() .then((accounts) => { if (accounts.length > 0) { const signer = provider.getSigner(accounts[0]); setSigner(signer); signer.getAddress().then((address) => { setAddress(address); }); signer.getBalance().then((balance) => { setBalance(balance.toString()); }); setIsConnected(true); } }) .catch((error) => { console.log(error); }) .finally(() => { // 增加finally设置isLoading为false,避免连接失败后一直处于加载状态 setIsLoading(false); }); }; const disconnect = () => { setIsLoading(true); magic.connect .disconnect() .then(() => { setAddress(null); setBalance(null); setIsConnected(false); }) .catch((error) => { console.log(error); }) .finally(() => { setIsLoading(false); }); }; return ( <AuthContext.Provider value={{ userDoc: userDoc?.docs[0]?.data() ?? {}, address, balance, isLoading: isLoading || dbLoading, isConnected, connect, disconnect, }} > {children} </AuthContext.Provider> ); };
改动说明
- 查询逻辑优化:通过三元判断,只有
address存在时才执行Firestore查询,未登录时不会发起无效查询,也不会触发后续的文档创建逻辑 - 文档创建防护:在
useEffect里增加address的判断,确保只有用户已连接(address有值)且查询不到对应文档时,才创建新用户文档 - 加载状态修复:给
connect方法增加finally,避免连接失败后页面一直处于加载状态
内容的提问来源于stack exchange,提问作者Herbie Vine
相关产品推荐
相关产品推荐

