joinmarket-webui / joinmarket-webui/jam
refactor: let react-query handle displaywallet UTXO changes
- Dominant language
- TypeScript
- Stars
- 330
- Forks
- 122
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 17
Description
# Refactor: Let React Query Handle `displaywallet` UTXO Changes
## Summary
Follow-up to #1448.
While working on #1448, we fixed the unnecessary initial wallet refetch caused by the `AFTER_UTXO_CHANGE` effect.
During the review, we discussed that instead of guarding this effect, a cleaner approach is to let React Query handle the dependency directly through the `displaywallet` query key.
This PR implements that follow-up approach.
---
## Problem
`useQueryDisplayWallet` already receives `utxosHashHex`, but it is currently passed through:
```ts
meta.cacheBuster
```
However, `meta` is not part of the generated `createQueryKey`.
The generated query key only considers values such as:
```text
_id
baseUrl
body
headers
path
query
```
As a result, changing `utxosHashHex` does not change the identity of the `displaywallet` query.
To keep the wallet information synchronized with UTXO changes, the application currently relies on the manual `AFTER_UTXO_CHANGE` effect.
### Current flow
```text
UTXO state changes
↓
utxosHashHex changes
↓
AFTER_UTXO_CHANGE effect
↓
refetchWalletBalance()
↓
/utxos + /displaywallet
↓
wallet state refreshed
```
This introduces a separate synchronization layer even though `displaywallet` is already managed by React Query.
---
## Approach
Make the UTXO state part of the `displaywallet` query identity.
When `utxosHashHex` changes:
```text
utxosHashHex changes
↓
displaywallet query key changes
↓
React Query detects a new query key
↓
displaywallet refetches automatically
```
Conceptually, the dependency becomes part of the query itself:
```ts
queryKey: [
// existing displaywallet query identity
utxosHashHex,
]
```
instead of relying on:
```text
utxosHashHex
↓
useEffect
↓
AFTER_UTXO_CHANGE
↓
manual refetch
```
---
## Before
```text
utxosHashHex
│
▼
WalletInfoAutoReload
│
▼
AFTER_UTXO_CHANGE
│
▼
refetchWalletBalance()
│ │
▼ ▼
/utxos /displaywallet
```
## After
```text
utxosHashHex
│
▼
displaywallet query key
│
▼
React Query
│
▼
/displaywallet
```
---
## Changes
- Make `utxosHashHex` part of the `displaywallet` query identity
- Let React Query handle `displaywallet` refetches when the UTXO state changes
- Remove the now-unnecessary manual `AFTER_UTXO_CHANGE` refetch path
- Simplify the wallet auto-reload flow
- Update the related tests for the query-key based behavior
---
## Why This Is Better
The previous implementation manually synchronized two pieces of state:
```text
UTXO state
↓
effect
↓
wallet state
```
With the query-key approach, the dependency is expressed directly where the data is fetched:
```text
UTXO state
↓
query identity
↓
React Query
↓
wallet state
```
This removes the need for a separate effect whose only responsibility is triggering another refetch.
It also makes React Query responsible for the cache/refetch behavior instead of duplicating that responsibility inside `WalletInfoAutoReload`.
---
## Relation to #1448
#1448 addressed the immediate issue by preventing the initial `AFTER_UTXO_CHANGE` execution from causing an unnecessary wallet refetch.
```text
#1448
│
▼
Guard unnecessary initial refetch
```
During its review, we identified a cleaner follow-up:
```text
#1448
│
▼
Guard AFTER_UTXO_CHANGE
│
▼
This PR
│
▼
Move UTXO dependency into query key
│
▼
Let React Query handle the refetch
│
▼
Remove manual AFTER_UTXO_CHANGE path
```
This PR implements that follow-up and simplifies the underlying approach rather than adding another guard around the existing effect.
---
## Testing
The related tests cover the new query-key based behavior and verify that:
- `displaywallet` continues to load normally
- UTXO state changes update `utxosHashHex`
- A changed `utxosHashHex` changes the relevant query identity
- React Query performs the expected `displaywallet` refetch
- The manual `AFTER_UTXO_CHANGE` refetch path is no longer required
- Existing wallet refresh behavior remains intact
---
## Result
The wallet refresh flow moves from:
```text
UTXO change
→ detect change manually
→ run effect
→ manually refetch wallet
```
to:
```text
UTXO change
→ query key changes
→ React Query handles refetch
```
This keeps the UTXO → `displaywallet` dependency in the query layer and simplifies the wallet auto-reload logic.
This is the follow-up approach discussed during the review of #1448.
Contributor guide
Research direction
Start with useQueryDisplayWallet and WalletInfoAutoReload, then inspect the related tests for the displaywallet query and AFTER_UTXO_CHANGE flow. Trace how utxosHashHex currently reaches meta.cacheBuster and how the generated query key is built. Done means UTXO changes update the query identity, the expected displaywallet refetch occurs, and the manual refetch path is no longer required.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend
- Issue type
- Refactor
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100