Skip to content

Commit 25beb60

Browse files
authored
fix: default useAccount hook to fetch and watch automatically (#124)
Update useAccount to default `fetch` and `watch` options to `true`, matching useBalance behavior. This ensures account data is retrieved automatically without requiring explicit options. Closes #112
1 parent 9dc98c6 commit 25beb60

File tree

3 files changed

+47
-11
lines changed

3 files changed

+47
-11
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@solana/react-hooks": patch
3+
---
4+
5+
Fix useAccount hook to default `fetch` and `watch` options to `true`, matching the behavior of useBalance. This ensures account data is fetched and watched automatically without requiring explicit options.

packages/react-hooks/src/hooks.account.test.tsx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,44 @@ describe('account hooks', () => {
4242
expect(subscription?.abort).toHaveBeenCalledTimes(1);
4343
});
4444

45-
it('skips fetches when disabled and when no address is provided', async () => {
45+
it('defaults to fetch and watch enabled', async () => {
4646
const address = createAddress(2);
47+
const { client, unmount } = renderHookWithClient(() => useAccount(address));
48+
49+
// Should fetch by default
50+
await waitFor(() => {
51+
expect(client.actions.fetchAccount).toHaveBeenCalledWith(address, undefined);
52+
});
53+
54+
// Should watch by default
55+
expect(client.watchers.watchAccount).toHaveBeenCalledWith(
56+
{ address, commitment: undefined },
57+
expect.any(Function),
58+
);
59+
60+
const subscription = client.watchers.watchAccount.mock.results[0]?.value;
61+
unmount();
62+
expect(subscription?.abort).toHaveBeenCalledTimes(1);
63+
});
64+
65+
it('skips fetches when disabled and when no address is provided', async () => {
66+
const address = createAddress(3);
4767
const { client, result } = renderHookWithClient(() => useAccount(undefined, { commitment: 'confirmed' }));
4868
expect(result.current).toBeUndefined();
4969
expect(client.actions.fetchAccount).not.toHaveBeenCalled();
5070
expect(client.watchers.watchAccount).not.toHaveBeenCalled();
5171

52-
const { client: clientWithSkip } = renderHookWithClient(() => useAccount(address, { fetch: false }));
72+
const { client: clientWithSkip } = renderHookWithClient(() =>
73+
useAccount(address, { fetch: false, watch: false }),
74+
);
5375
await waitFor(() => {
5476
expect(clientWithSkip.actions.fetchAccount).not.toHaveBeenCalled();
5577
});
5678
expect(clientWithSkip.watchers.watchAccount).not.toHaveBeenCalled();
5779
});
5880

5981
it('tracks lamport balances and watcher state', async () => {
60-
const address = createAddress(3);
82+
const address = createAddress(4);
6183
const entry = createAccountEntry({
6284
address,
6385
fetching: true,
@@ -102,7 +124,7 @@ describe('account hooks', () => {
102124
});
103125

104126
it('respects skip options when monitoring balances', async () => {
105-
const address = createAddress(4);
127+
const address = createAddress(5);
106128
const { client } = renderHookWithClient(() => useBalance(address, { fetch: false, watch: false }));
107129

108130
await waitFor(() => {

packages/react-hooks/src/hooks.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,16 @@ export function useSplToken(
617617
*/
618618
export function useAccount(addressLike?: AddressLike, options: UseAccountOptions = {}): AccountCacheEntry | undefined {
619619
const client = useSolanaClient();
620-
const shouldSkip = options.skip ?? !addressLike;
620+
const mergedOptions = useMemo(
621+
() => ({
622+
commitment: options.commitment,
623+
fetch: options.fetch ?? true,
624+
skip: options.skip,
625+
watch: options.watch ?? true,
626+
}),
627+
[options.commitment, options.fetch, options.skip, options.watch],
628+
);
629+
const shouldSkip = mergedOptions.skip ?? !addressLike;
621630
const { address, addressError } = useMemo(() => {
622631
if (shouldSkip || !addressLike) {
623632
return { address: undefined, addressError: undefined };
@@ -640,12 +649,12 @@ export function useAccount(addressLike?: AddressLike, options: UseAccountOptions
640649
const account = useClientStore(selector);
641650

642651
useSuspenseFetcher({
643-
enabled: options.fetch !== false && !shouldSkip && Boolean(address),
652+
enabled: mergedOptions.fetch !== false && !shouldSkip && Boolean(address),
644653
fetcher: () => {
645654
if (!address) {
646655
throw new Error('Provide an address before fetching account data.');
647656
}
648-
return client.actions.fetchAccount(address, options.commitment);
657+
return client.actions.fetchAccount(address, mergedOptions.commitment);
649658
},
650659
key: accountKey ?? null,
651660
ready: account !== undefined,
@@ -655,18 +664,18 @@ export function useAccount(addressLike?: AddressLike, options: UseAccountOptions
655664
if (!address) {
656665
return;
657666
}
658-
const commitment = options.commitment;
659-
if (options.fetch !== false && account === undefined) {
667+
const commitment = mergedOptions.commitment;
668+
if (mergedOptions.fetch !== false && account === undefined) {
660669
void client.actions.fetchAccount(address, commitment).catch(() => undefined);
661670
}
662-
if (options.watch) {
671+
if (mergedOptions.watch) {
663672
const subscription = client.watchers.watchAccount({ address, commitment }, () => undefined);
664673
return () => {
665674
subscription.abort();
666675
};
667676
}
668677
return undefined;
669-
}, [account, address, client, options.commitment, options.fetch, options.watch]);
678+
}, [account, address, client, mergedOptions.commitment, mergedOptions.fetch, mergedOptions.watch]);
670679

671680
return account;
672681
}

0 commit comments

Comments
 (0)