题目
用户在 DApp 里完成一笔转账,钱包显示成功,链上也能查到这笔交易,但页面顶部的余额仍然是转账前的数字;刷新页面后数值才更新。请说明你会从哪里开始排查,以及修复方案。
考察目标
- 交易收据与前端查询缓存之间的关系。
- 失效(invalidation)与重新取数的触发时机。
- 缓存键对账户与链的隔离。
- 节点视图差异带来的显示偏差。
从查询缓存、失效时机、区块推进与节点视图差异几个层面排查「交易已确认但界面仍是旧值」的问题。
用户在 DApp 里完成一笔转账,钱包显示成功,链上也能查到这笔交易,但页面顶部的余额仍然是转账前的数字;刷新页面后数值才更新。请说明你会从哪里开始排查,以及修复方案。
交易收据描述的是一笔交易在某个区块中的执行结果,它由节点按交易哈希返回;页面上的余额来自某次读请求的结果或本地缓存,两者不是同一个数据源。读请求的时间点与缓存是否仍然有效,决定界面何时显示新数值。实现差异与工程取舍见深入回答。
import { useQueryClient } from "@tanstack/react-query";
import { useEffect } from "react";
import { useBalance, useBlockNumber } from "wagmi";
// 省略了 WagmiProvider、QueryClientProvider 与错误处理的上下文。
function BalanceWatcher({ address }: { address: `0x${string}` }) {
const queryClient = useQueryClient();
const { data: blockNumber } = useBlockNumber({ watch: true });
const { data: balance, queryKey } = useBalance({ address });
useEffect(() => {
// 区块推进后把余额查询标记为过期,已渲染的查询会重新取数。
void queryClient.invalidateQueries({ queryKey });
}, [blockNumber, queryClient, queryKey]);
return <span>{balance?.formatted ?? "—"}</span>;
}
发现这道题有问题? 反馈此题