React Query + LocalStorage 报错:Cannot read properties of null (reading 'id')
解决TypeError与React Query数据获取失效问题
问题根源
初始渲染时userData是null(localStorage未存储登录数据),直接访问userData.id或userData.type触发Cannot read properties of null错误。加可选链后报错消失,但enabled选项里的userData.id.length会变成undefined.length,导致React Query始终不执行查询,自然拿不到数据,invalidateQueries也找不到对应缓存key。
修复方案
1. 修正useGetParcels的空值处理与类型定义
将入参类型改为User | null,内部做完整空值校验,同时修正enabled条件确保仅当用户数据有效时执行查询:
import { getBikerParcels } from "@/models/bikerModels"; import { getSenderParcels } from "@/models/senderModels"; import { User } from "@/types/dataTypes"; import { useQuery } from "@tanstack/react-query"; // 允许入参为null const useGetParcels = (userData: User | null) => { return useQuery( // 仅当userData存在时携带id,避免缓存key混乱 userData ? ["user-parcels", userData.id] : ["user-parcels", "empty"], async () => { // 提前判断,阻断后续无效代码执行 if (!userData) return []; let res; if (userData.type === "biker") { res = await getBikerParcels(userData.id); } else if (userData.type === "sender") { res = await getSenderParcels(userData.id); } // 加可选链防止res或res.data为undefined,兜底返回空数组 return res?.data?.parcels || []; }, { staleTime: 1000 * 60 * 100, // 仅当userData存在且id有效时启用查询 enabled: !!userData?.id, } ); }; export default useGetParcels;
2. 在页面组件中处理userData为null的场景
初始渲染时若userData为null,直接显示登录提示或加载状态,避免无意义的查询调用:
"use client"; import React from "react"; import SenderTable from "./senderTable"; import useLocalStorage from "@/hooks/useLocalStorage"; import BikerTable from "./bikerTable"; import useGetParcels from "@/hooks/queries/useGetParcels"; import Loading from "@/components/Loading"; import Nav from "@/components/Nav"; export default function Dashboard() { const [userData] = useLocalStorage("userData", null); const { data: parcels, isLoading, error } = useGetParcels(userData); // 处理未登录状态 if (!userData) { return <div>请先登录</div>; } if (isLoading) { return <Loading />; } if (error) { return <div>数据加载失败:{error.message}</div>; } return ( <> {userData.type === "sender" && <Nav />} {userData.type === "sender" ? ( <SenderTable parcels={parcels} /> ) : ( <BikerTable parcels={parcels} /> )} </> ); }
3. 正确调用invalidateQueries
确保缓存key与useQuery定义一致,比如数据更新或登录后:
// 示例:在更新操作后刷新数据 queryClient.invalidateQueries({ queryKey: ["user-parcels", userData.id] });
关键说明
- 入参类型修改:明确
userData可能为null,避免TypeScript报错 - 查询key优化:空状态用固定值作为key,防止生成无效key导致缓存混乱
- 提前空值校验:在查询函数开头判断userData,避免后续代码访问null属性
- enabled条件修正:用
!!userData?.id确保仅当id存在且有效时执行查询
内容的提问来源于stack exchange,提问作者Abdulaziz omar
相关产品推荐
相关产品推荐

