I am an YNAB heavy user. While learning React Query I decided to create a demo that uses YNAB API. This file describes the high-level process of the demo development and my findings.
The full code is here. I've also added links to particular files/commits (denoted as 📄).
Assumptions
- relying on React Query as much as possible
- very basic. Two queries, one mutation. Enough is enough.
- using React Navigation for simplicity
- diching the styling
Log
Initial configuration
I've decided to use create-react-app
just for the sake of simplicity.
I've created an API client (📄) for YNAB using apisauce
and added first query (📄) (a function that fetches budgets from YNAB; getBudgets
).
Then I've created a BudgetSelectionScreen
(📄) (In YNAB you can keep tabs on several budgets with one subscribtion and I wanted to use a testing one anyway).
Adding queries
I configured the QueryClient (📄) and with useQuery hook I utilised the getBudgets
query from before and rendered links to a details screen (📄).
I moved the app to React Native Web to be able to use React Navigation. I've added BudgetDetailsScreen
and passed the selected budgetId
to it via props.
In the meantime I learned the QueryClient shouldn't live inside the React App so I moved it outside (📄) (and added useful React Query Devtools) (📄).
Then I've added another query (📄) for fetching the transactions for a given budgetId
. This is where I learned about preferred way of passing parameters to the queries. Ultimately I rendered the transactions.
Adding mutation
I wanted to have a way of adding the transactions to my YNAB budget. In React Query it's done with useMutation hook.
I've created a separate component (📄) for the Add Transaction form that had 2 inputs (Payee and Amount) and a button that ran the mutation.
Invalidating the cached query
Lastly, I wanted to make sure the transactions the I see in my little app reflect the ones that are, in fact, in my budget. To do that I just needed to invalidate the query created 2 paragraphs above.
To do that I just needed to call the invalidateQueries
method of the QueryClient
in the onSuccess
callback of the mutation (📄.).
And that's it. Honestly? It was great.
Conclusions
It was a breeze. I didn't know this library before and right now I think it'll be my preferred way of handling the state of the remote servers. I just scratched the surface and yet I was able to quickly create a pretty neat demo that is performant and features-rich. And the best part is that I didn't have to think of how to develop those features. Nicely done, Tanner 🙌.