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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 11:04:59