From f95df06800d12c117a3015804566aa54c2919a99 Mon Sep 17 00:00:00 2001
From: Joel Jeremy Marquez <joeljeremy.marquez@gmail.com>
Date: Tue, 5 Dec 2023 13:14:37 -0800
Subject: [PATCH] [Maintenance] ESLint: prefer-const components folder part 1
 (#2033)

* ESLint prefer-const components folder part 1

* Release notes
---
 .eslintrc.js                                  |  22 ++-
 .../src/components/accounts/Account.js        | 176 +++++++++---------
 .../components/accounts/AccountSyncCheck.js   |  18 +-
 .../src/components/accounts/Balance.js        |  22 +--
 .../src/components/accounts/Header.js         |   8 +-
 .../src/components/accounts/MobileAccount.js  |  18 +-
 .../accounts/MobileAccountDetails.js          |   2 +-
 .../src/components/accounts/MobileAccounts.js |  12 +-
 .../src/components/accounts/Reconcile.js      |  16 +-
 .../components/autocomplete/Autocomplete.tsx  |  22 +--
 .../autocomplete/CategoryAutocomplete.tsx     |   2 +-
 .../autocomplete/PayeeAutocomplete.tsx        |  36 ++--
 .../autocomplete/SavedFilterAutocomplete.tsx  |   2 +-
 .../budget/BalanceWithCarryover.tsx           |  10 +-
 .../src/components/budget/BudgetCategories.js |  14 +-
 .../budget/BudgetMonthCountContext.tsx        |   5 +-
 .../components/budget/BudgetPageHeader.tsx    |   4 +-
 .../src/components/budget/BudgetSummaries.tsx |  22 +--
 .../src/components/budget/BudgetTable.js      |  28 +--
 .../components/budget/DynamicBudgetTable.tsx  |  14 +-
 .../src/components/budget/ExpenseCategory.tsx |   4 +-
 .../src/components/budget/ExpenseGroup.tsx    |   8 +-
 .../src/components/budget/IncomeCategory.tsx  |   4 +-
 .../src/components/budget/MobileBudget.js     |  49 ++---
 .../components/budget/MobileBudgetTable.js    | 104 +++++------
 .../components/budget/MonthCountSelector.tsx  |   4 +-
 .../src/components/budget/MonthPicker.tsx     |   2 +-
 .../src/components/budget/MonthsContext.tsx   |   8 +-
 .../src/components/budget/RenderMonths.tsx    |   4 +-
 .../src/components/budget/index.tsx           |  62 +++---
 .../budget/report/BalanceTooltip.tsx          |   4 +-
 .../budget/report/ReportComponents.tsx        |   6 +-
 .../budget/report/ReportContext.tsx           |   4 +-
 .../report/budgetsummary/BudgetSummary.tsx    |   6 +-
 .../report/budgetsummary/ExpenseProgress.tsx  |   2 +-
 .../report/budgetsummary/IncomeProgress.tsx   |   4 +-
 .../report/budgetsummary/PieProgress.tsx      |   8 +-
 .../budget/report/budgetsummary/Saved.tsx     |  12 +-
 .../budget/rollover/BalanceTooltip.tsx        |   8 +-
 .../budget/rollover/CoverTooltip.tsx          |   2 +-
 .../budget/rollover/RolloverComponents.tsx    |   6 +-
 .../budget/rollover/RolloverContext.tsx       |   4 +-
 .../budget/rollover/TransferTooltip.tsx       |  10 +-
 .../rollover/budgetsummary/BudgetSummary.tsx  |   8 +-
 .../rollover/budgetsummary/ToBudget.tsx       |  14 +-
 .../rollover/budgetsummary/TotalsList.tsx     |   8 +-
 .../src/components/budget/util.ts             |  18 +-
 .../src/components/common/AnchorLink.tsx      |   2 +-
 .../src/components/common/Button.tsx          |   8 +-
 .../src/components/common/ExternalLink.tsx    |   2 +-
 .../src/components/common/HoverTarget.tsx     |   2 +-
 .../src/components/common/InitialFocus.tsx    |   2 +-
 .../src/components/common/Input.tsx           |   2 +-
 .../components/common/InputWithContent.tsx    |   2 +-
 .../src/components/common/Menu.tsx            |  16 +-
 .../src/components/common/Modal.tsx           |  12 +-
 .../src/components/common/Stack.tsx           |   2 +-
 .../src/components/filters/FiltersMenu.js     |  44 ++---
 .../src/components/filters/SavedFilters.js    |  16 +-
 .../src/components/manager/BudgetList.js      |  14 +-
 .../src/components/manager/ConfigServer.tsx   |  18 +-
 .../src/components/manager/DeleteFile.js      |   4 +-
 .../src/components/manager/Import.tsx         |   2 +-
 .../src/components/manager/ManagementApp.js   |  10 +-
 .../src/components/manager/Modals.js          |   8 +-
 .../src/components/manager/WelcomeScreen.tsx  |   2 +-
 .../manager/subscribe/Bootstrap.tsx           |   8 +-
 .../manager/subscribe/ChangePassword.tsx      |   8 +-
 .../manager/subscribe/ConfirmPasswordForm.tsx |   8 +-
 .../components/manager/subscribe/Error.tsx    |   6 +-
 .../components/manager/subscribe/Login.tsx    |  12 +-
 .../components/manager/subscribe/common.tsx   |  20 +-
 .../components/mobile/MobileAmountInput.js    |   4 +-
 .../src/components/modals/CloseAccount.tsx    |  14 +-
 .../components/modals/CreateEncryptionKey.tsx |  12 +-
 .../components/modals/CreateLocalAccount.tsx  |  24 +--
 .../src/components/modals/EditField.js        |  16 +-
 .../src/components/modals/EditRule.js         |  75 ++++----
 .../components/modals/FixEncryptionKey.tsx    |  12 +-
 .../modals/GoCardlessExternalMsg.tsx          |  18 +-
 .../components/modals/ImportTransactions.js   | 120 ++++++------
 .../src/components/modals/LoadBackup.js       |   2 +-
 .../components/modals/ManageRulesModal.tsx    |   4 +-
 .../components/modals/MergeUnusedPayees.js    |  26 +--
 .../components/modals/PlaidExternalMsg.tsx    |  10 +-
 upcoming-release-notes/2033.md                |   6 +
 86 files changed, 721 insertions(+), 678 deletions(-)
 create mode 100644 upcoming-release-notes/2033.md

diff --git a/.eslintrc.js b/.eslintrc.js
index d0eadff98..1c9425aa7 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -239,7 +239,27 @@ module.exports = {
         './packages/api/app/**/*',
         './packages/crdt/**/*',
         './packages/desktop-client/src/*',
-        // './packages/desktop-client/src/components/**/*',
+        // './packages/desktop-client/src/components/*',
+        './packages/desktop-client/src/components/accounts/**/*',
+        './packages/desktop-client/src/components/autocomplete/**/*',
+        './packages/desktop-client/src/components/budget/**/*',
+        './packages/desktop-client/src/components/common/**/*',
+        './packages/desktop-client/src/components/filters/**/*',
+        './packages/desktop-client/src/components/gocardless/**/*',
+        './packages/desktop-client/src/components/manager/**/*',
+        './packages/desktop-client/src/components/mobile/**/*',
+        './packages/desktop-client/src/components/modals/**/*',
+        // './packages/desktop-client/src/components/payees/**/*',
+        // './packages/desktop-client/src/components/reports/**/*',
+        // './packages/desktop-client/src/components/responsive/**/*',
+        // './packages/desktop-client/src/components/rules/**/*',
+        // './packages/desktop-client/src/components/schedules/**/*',
+        // './packages/desktop-client/src/components/select/**/*',
+        // './packages/desktop-client/src/components/settings/**/*',
+        // './packages/desktop-client/src/components/sidebar/**/*',
+        // './packages/desktop-client/src/components/spreadsheet/**/*',
+        // './packages/desktop-client/src/components/transactions/**/*',
+        // './packages/desktop-client/src/components/util/**/*',
         './packages/desktop-client/src/hooks/**/*',
         './packages/desktop-client/src/icons/**/*',
         './packages/desktop-client/src/style/**/*',
diff --git a/packages/desktop-client/src/components/accounts/Account.js b/packages/desktop-client/src/components/accounts/Account.js
index 8e047c7ab..378719162 100644
--- a/packages/desktop-client/src/components/accounts/Account.js
+++ b/packages/desktop-client/src/components/accounts/Account.js
@@ -89,11 +89,11 @@ function AllTransactions({
   children,
 }) {
   const { id: accountId } = account;
-  let scheduleData = useCachedSchedules();
+  const scheduleData = useCachedSchedules();
 
   transactions ??= [];
 
-  let schedules = useMemo(
+  const schedules = useMemo(
     () =>
       scheduleData
         ? scheduleData.schedules.filter(
@@ -107,7 +107,7 @@ function AllTransactions({
     [scheduleData],
   );
 
-  let prependTransactions = useMemo(() => {
+  const prependTransactions = useMemo(() => {
     return schedules.map(schedule => ({
       id: `preview/${schedule.id}`,
       payee: schedule._payee,
@@ -130,16 +130,16 @@ function AllTransactions({
       : 0;
   }, [showBalances, balances, transactions]);
 
-  let prependBalances = useMemo(() => {
+  const prependBalances = useMemo(() => {
     if (!showBalances) {
       return null;
     }
 
     // Reverse so we can calculate from earliest upcoming schedule.
-    let scheduledBalances = [...prependTransactions]
+    const scheduledBalances = [...prependTransactions]
       .reverse()
       .map(scheduledTransaction => {
-        let amount =
+        const amount =
           (scheduledTransaction._inverse ? -1 : 1) *
           getScheduledAmount(scheduledTransaction.amount);
         return {
@@ -150,7 +150,7 @@ function AllTransactions({
     return groupById(scheduledBalances);
   }, [showBalances, prependTransactions, runningBalance]);
 
-  let allTransactions = useMemo(() => {
+  const allTransactions = useMemo(() => {
     // Don't prepend scheduled transactions if we are filtering
     if (!filtered && prependTransactions.length > 0) {
       return prependTransactions.concat(transactions);
@@ -158,7 +158,7 @@ function AllTransactions({
     return transactions;
   }, [filtered, prependTransactions, transactions]);
 
-  let allBalances = useMemo(() => {
+  const allBalances = useMemo(() => {
     // Don't prepend scheduled transactions if we are filtering
     if (!filtered && prependBalances && balances) {
       return { ...prependBalances, ...balances };
@@ -217,7 +217,7 @@ class AccountInternal extends PureComponent {
   }
 
   async componentDidMount() {
-    let maybeRefetch = tables => {
+    const maybeRefetch = tables => {
       if (
         tables.includes('transactions') ||
         tables.includes('category_mapping') ||
@@ -227,7 +227,7 @@ class AccountInternal extends PureComponent {
       }
     };
 
-    let onUndo = async ({ tables, messages, undoTag }) => {
+    const onUndo = async ({ tables, messages, undoTag }) => {
       await maybeRefetch(tables);
 
       // If all the messages are dealing with transactions, find the
@@ -239,7 +239,7 @@ class AccountInternal extends PureComponent {
         messages.every(msg => msg.dataset === 'transactions') &&
         !messages.find(msg => msg.column === 'tombstone')
       ) {
-        let focusableMsgs = messages.filter(
+        const focusableMsgs = messages.filter(
           msg =>
             msg.dataset === 'transactions' && !(msg.column === 'tombstone'),
         );
@@ -265,7 +265,7 @@ class AccountInternal extends PureComponent {
       this.props.setLastUndoState(null);
     };
 
-    let unlistens = [listen('undo-event', onUndo)];
+    const unlistens = [listen('undo-event', onUndo)];
 
     this.unlisten = () => {
       unlistens.forEach(unlisten => unlisten());
@@ -317,7 +317,7 @@ class AccountInternal extends PureComponent {
   }
 
   fetchAllIds = async () => {
-    let { data } = await runQuery(this.paged.getQuery().select('id'));
+    const { data } = await runQuery(this.paged.getQuery().select('id'));
     // Remember, this is the `grouped` split type so we need to deal
     // with the `subtransactions` property
     return data.reduce((arr, t) => {
@@ -332,7 +332,7 @@ class AccountInternal extends PureComponent {
   };
 
   fetchTransactions = () => {
-    let query = this.makeRootQuery();
+    const query = this.makeRootQuery();
     this.rootQuery = this.currentQuery = query;
     this.updateQuery(query);
 
@@ -342,8 +342,8 @@ class AccountInternal extends PureComponent {
   };
 
   makeRootQuery = () => {
-    let locationState = this.props.location.state;
-    let accountId = this.props.accountId;
+    const locationState = this.props.location.state;
+    const accountId = this.props.accountId;
 
     if (locationState && locationState.filter) {
       return q('transactions')
@@ -488,12 +488,12 @@ class AccountInternal extends PureComponent {
   };
 
   onExport = async accountName => {
-    let exportedTransactions = await send('transactions-export-query', {
+    const exportedTransactions = await send('transactions-export-query', {
       query: this.currentQuery.serialize(),
     });
-    let normalizedName =
+    const normalizedName =
       accountName && accountName.replace(/[()]/g, '').replace(/\s+/g, '-');
-    let filename = `${normalizedName || 'transactions'}.csv`;
+    const filename = `${normalizedName || 'transactions'}.csv`;
 
     window.Actual.saveFile(
       exportedTransactions,
@@ -523,8 +523,10 @@ class AccountInternal extends PureComponent {
   };
 
   canCalculateBalance = () => {
-    let accountId = this.props.accountId;
-    let account = this.props.accounts.find(account => account.id === accountId);
+    const accountId = this.props.accountId;
+    const account = this.props.accounts.find(
+      account => account.id === accountId,
+    );
     return (
       account &&
       this.state.search === '' &&
@@ -540,7 +542,7 @@ class AccountInternal extends PureComponent {
       return null;
     }
 
-    let { data } = await runQuery(
+    const { data } = await runQuery(
       this.paged
         .getQuery()
         .options({ splits: 'none' })
@@ -570,8 +572,8 @@ class AccountInternal extends PureComponent {
   };
 
   onToggleExtraBalances = () => {
-    let { accountId, showExtraBalances } = this.props;
-    let key = 'show-extra-balances-' + accountId || 'all-accounts';
+    const { accountId, showExtraBalances } = this.props;
+    const key = 'show-extra-balances-' + accountId || 'all-accounts';
 
     this.props.savePrefs({ [key]: !showExtraBalances });
   };
@@ -622,7 +624,7 @@ class AccountInternal extends PureComponent {
         break;
       case 'remove-sorting': {
         this.setState({ sort: [] }, () => {
-          let filters = this.state.filters;
+          const filters = this.state.filters;
           if (filters.length > 0) {
             this.applyFilters([...filters]);
           } else {
@@ -648,7 +650,7 @@ class AccountInternal extends PureComponent {
   };
 
   getAccountTitle(account, id) {
-    let { filterName } = this.props.location.state || {};
+    const { filterName } = this.props.location.state || {};
 
     if (filterName) {
       return filterName;
@@ -686,7 +688,7 @@ class AccountInternal extends PureComponent {
   };
 
   onCreatePayee = name => {
-    let trimmed = name.trim();
+    const trimmed = name.trim();
     if (trimmed !== '') {
       return this.props.createPayee(name);
     }
@@ -696,9 +698,9 @@ class AccountInternal extends PureComponent {
   lockTransactions = async () => {
     this.setState({ workingHard: true });
 
-    let { accountId } = this.props;
+    const { accountId } = this.props;
 
-    let { data } = await runQuery(
+    const { data } = await runQuery(
       q('transactions')
         .filter({ cleared: true, reconciled: false, account: accountId })
         .select('*')
@@ -706,10 +708,10 @@ class AccountInternal extends PureComponent {
     );
     let transactions = ungroupTransactions(data);
 
-    let changes = { updated: [] };
+    const changes = { updated: [] };
 
     transactions.forEach(trans => {
-      let { diff } = updateTransaction(transactions, {
+      const { diff } = updateTransaction(transactions, {
         ...trans,
         reconciled: true,
       });
@@ -730,16 +732,16 @@ class AccountInternal extends PureComponent {
   };
 
   onDoneReconciling = async () => {
-    let { accountId } = this.props;
-    let { reconcileAmount } = this.state;
+    const { accountId } = this.props;
+    const { reconcileAmount } = this.state;
 
-    let { data } = await runQuery(
+    const { data } = await runQuery(
       q('transactions')
         .filter({ cleared: true, account: accountId })
         .select('*')
         .options({ splits: 'grouped' }),
     );
-    let transactions = ungroupTransactions(data);
+    const transactions = ungroupTransactions(data);
 
     let cleared = 0;
 
@@ -749,7 +751,7 @@ class AccountInternal extends PureComponent {
       }
     });
 
-    let targetDiff = reconcileAmount - cleared;
+    const targetDiff = reconcileAmount - cleared;
 
     if (targetDiff === 0) {
       await this.lockTransactions();
@@ -792,10 +794,10 @@ class AccountInternal extends PureComponent {
   };
 
   onBatchEdit = async (name, ids) => {
-    let onChange = async (name, value) => {
+    const onChange = async (name, value) => {
       this.setState({ workingHard: true });
 
-      let { data } = await runQuery(
+      const { data } = await runQuery(
         q('transactions')
           .filter({ id: { $oneof: ids } })
           .select('*')
@@ -803,7 +805,7 @@ class AccountInternal extends PureComponent {
       );
       let transactions = ungroupTransactions(data);
 
-      let changes = { deleted: [], updated: [] };
+      const changes = { deleted: [], updated: [] };
 
       // Cleared is a special case right now
       if (name === 'cleared') {
@@ -826,7 +828,7 @@ class AccountInternal extends PureComponent {
           return;
         }
 
-        let transaction = {
+        const transaction = {
           ...trans,
           [name]: value,
         };
@@ -835,7 +837,7 @@ class AccountInternal extends PureComponent {
           transaction.reconciled = false;
         }
 
-        let { diff } = updateTransaction(transactions, transaction);
+        const { diff } = updateTransaction(transactions, transaction);
 
         // TODO: We need to keep an updated list of transactions so
         // the logic in `updateTransaction`, particularly about
@@ -863,13 +865,13 @@ class AccountInternal extends PureComponent {
     };
 
     if (name === 'amount' || name === 'payee' || name === 'account') {
-      let { data } = await runQuery(
+      const { data } = await runQuery(
         q('transactions')
           .filter({ id: { $oneof: ids }, reconciled: true })
           .select('*')
           .options({ splits: 'grouped' }),
       );
-      let transactions = ungroupTransactions(data);
+      const transactions = ungroupTransactions(data);
 
       if (transactions.length > 0) {
         this.props.pushModal('confirm-transaction-edit', {
@@ -892,17 +894,17 @@ class AccountInternal extends PureComponent {
   };
 
   onBatchDuplicate = async ids => {
-    let onConfirmDuplicate = async ids => {
+    const onConfirmDuplicate = async ids => {
       this.setState({ workingHard: true });
 
-      let { data } = await runQuery(
+      const { data } = await runQuery(
         q('transactions')
           .filter({ id: { $oneof: ids } })
           .select('*')
           .options({ splits: 'grouped' }),
       );
 
-      let changes = {
+      const changes = {
         added: data
           .reduce((newTransactions, trans) => {
             return newTransactions.concat(
@@ -925,10 +927,10 @@ class AccountInternal extends PureComponent {
   };
 
   onBatchDelete = async ids => {
-    let onConfirmDelete = async ids => {
+    const onConfirmDelete = async ids => {
       this.setState({ workingHard: true });
 
-      let { data } = await runQuery(
+      const { data } = await runQuery(
         q('transactions')
           .filter({ id: { $oneof: ids } })
           .select('*')
@@ -936,11 +938,11 @@ class AccountInternal extends PureComponent {
       );
       let transactions = ungroupTransactions(data);
 
-      let idSet = new Set(ids);
-      let changes = { deleted: [], updated: [] };
+      const idSet = new Set(ids);
+      const changes = { deleted: [], updated: [] };
 
       transactions.forEach(trans => {
-        let parentId = trans.parent_id;
+        const parentId = trans.parent_id;
 
         // First, check if we're actually deleting this transaction by
         // checking `idSet`. Then, we don't need to do anything if it's
@@ -949,7 +951,7 @@ class AccountInternal extends PureComponent {
           return;
         }
 
-        let { diff } = deleteTransaction(transactions, trans.id);
+        const { diff } = deleteTransaction(transactions, trans.id);
 
         // TODO: We need to keep an updated list of transactions so
         // the logic in `updateTransaction`, particularly about
@@ -977,13 +979,13 @@ class AccountInternal extends PureComponent {
   };
 
   checkForReconciledTransactions = async (ids, confirmReason, onConfirm) => {
-    let { data } = await runQuery(
+    const { data } = await runQuery(
       q('transactions')
         .filter({ id: { $oneof: ids }, reconciled: true })
         .select('*')
         .options({ splits: 'grouped' }),
     );
-    let transactions = ungroupTransactions(data);
+    const transactions = ungroupTransactions(data);
     if (transactions.length > 0) {
       this.props.pushModal('confirm-transaction-edit', {
         onConfirm: () => {
@@ -1005,14 +1007,14 @@ class AccountInternal extends PureComponent {
   };
 
   onCreateRule = async ids => {
-    let { data } = await runQuery(
+    const { data } = await runQuery(
       q('transactions')
         .filter({ id: { $oneof: ids } })
         .select('*')
         .options({ splits: 'grouped' }),
     );
-    let transactions = ungroupTransactions(data);
-    let payeeCondition = transactions[0].imported_payee
+    const transactions = ungroupTransactions(data);
+    const payeeCondition = transactions[0].imported_payee
       ? {
           field: 'imported_payee',
           op: 'is',
@@ -1026,7 +1028,7 @@ class AccountInternal extends PureComponent {
           type: 'id',
         };
 
-    let rule = {
+    const rule = {
       stage: null,
       conditionsOp: 'and',
       conditions: [payeeCondition],
@@ -1054,7 +1056,7 @@ class AccountInternal extends PureComponent {
 
   onReloadSavedFilter = (savedFilter, item) => {
     if (item === 'reload') {
-      let [getFilter] = this.props.filtersList.filter(
+      const [getFilter] = this.props.filtersList.filter(
         f => f.id === this.state.filterId.id,
       );
       this.setState({ conditionsOp: getFilter.conditionsOp });
@@ -1136,15 +1138,15 @@ class AccountInternal extends PureComponent {
   onScheduleAction = async (name, ids) => {
     switch (name) {
       case 'post-transaction':
-        for (let id of ids) {
-          let parts = id.split('/');
+        for (const id of ids) {
+          const parts = id.split('/');
           await send('schedule/post-transaction', { id: parts[1] });
         }
         this.refetchTransactions();
         break;
       case 'skip':
-        for (let id of ids) {
-          let parts = id.split('/');
+        for (const id of ids) {
+          const parts = id.split('/');
           await send('schedule/skip-next-date', { id: parts[1] });
         }
         break;
@@ -1154,10 +1156,10 @@ class AccountInternal extends PureComponent {
 
   applyFilters = async conditions => {
     if (conditions.length > 0) {
-      let customFilters = conditions
+      const customFilters = conditions
         .filter(cond => !!cond.customName)
         .map(f => f.filter);
-      let { filters } = await send('make-filters-from-conditions', {
+      const { filters } = await send('make-filters-from-conditions', {
         conditions: conditions.filter(cond => !cond.customName),
       });
       const conditionsOpKey = this.state.conditionsOp === 'or' ? '$or' : '$and';
@@ -1187,13 +1189,13 @@ class AccountInternal extends PureComponent {
   };
 
   applySort = (field, ascDesc, prevField, prevAscDesc) => {
-    let filters = this.state.filters;
-    let sortField = getField(!field ? this.state.sort.field : field);
-    let sortAscDesc = !ascDesc ? this.state.sort.ascDesc : ascDesc;
-    let sortPrevField = getField(
+    const filters = this.state.filters;
+    const sortField = getField(!field ? this.state.sort.field : field);
+    const sortAscDesc = !ascDesc ? this.state.sort.ascDesc : ascDesc;
+    const sortPrevField = getField(
       !prevField ? this.state.sort.prevField : prevField,
     );
-    let sortPrevAscDesc = !prevField
+    const sortPrevAscDesc = !prevField
       ? this.state.sort.prevAscDesc
       : prevAscDesc;
 
@@ -1263,7 +1265,7 @@ class AccountInternal extends PureComponent {
   };
 
   render() {
-    let {
+    const {
       accounts,
       categoryGroups,
       payees,
@@ -1277,7 +1279,7 @@ class AccountInternal extends PureComponent {
       accountId,
       categoryId,
     } = this.props;
-    let {
+    const {
       transactions,
       loading,
       workingHard,
@@ -1290,7 +1292,7 @@ class AccountInternal extends PureComponent {
       showCleared,
     } = this.state;
 
-    let account = accounts.find(account => account.id === accountId);
+    const account = accounts.find(account => account.id === accountId);
     const accountName = this.getAccountTitle(account, accountId);
 
     if (!accountName && !loading) {
@@ -1299,19 +1301,19 @@ class AccountInternal extends PureComponent {
       return <Navigate to="/accounts" replace />;
     }
 
-    let category = categoryGroups
+    const category = categoryGroups
       .flatMap(g => g.categories)
       .find(category => category.id === categoryId);
 
-    let showEmptyMessage = !loading && !accountId && accounts.length === 0;
+    const showEmptyMessage = !loading && !accountId && accounts.length === 0;
 
-    let isNameEditable =
+    const isNameEditable =
       accountId &&
       accountId !== 'budgeted' &&
       accountId !== 'offbudget' &&
       accountId !== 'uncategorized';
 
-    let balanceQuery = this.getBalanceQuery(account, accountId);
+    const balanceQuery = this.getBalanceQuery(account, accountId);
 
     return (
       <AllTransactions
@@ -1459,8 +1461,8 @@ class AccountInternal extends PureComponent {
 }
 
 function AccountHack(props) {
-  let { dispatch: splitsExpandedDispatch } = useSplitsExpanded();
-  let match = useMatch(props.location.pathname);
+  const { dispatch: splitsExpandedDispatch } = useSplitsExpanded();
+  const match = useMatch(props.location.pathname);
 
   return (
     <AccountInternal
@@ -1472,11 +1474,11 @@ function AccountHack(props) {
 }
 
 export default function Account() {
-  let params = useParams();
-  let location = useLocation();
+  const params = useParams();
+  const location = useLocation();
 
-  let { grouped: categoryGroups } = useCategories();
-  let state = useSelector(state => ({
+  const { grouped: categoryGroups } = useCategories();
+  const state = useSelector(state => ({
     newTransactions: state.queries.newTransactions,
     matchedTransactions: state.queries.matchedTransactions,
     accounts: state.queries.accounts,
@@ -1494,14 +1496,14 @@ export default function Account() {
     lastUndoState: state.app.lastUndoState,
   }));
 
-  let dispatch = useDispatch();
-  let filtersList = useFilters();
-  let actionCreators = useMemo(
+  const dispatch = useDispatch();
+  const filtersList = useFilters();
+  const actionCreators = useMemo(
     () => bindActionCreators(actions, dispatch),
     [dispatch],
   );
 
-  let transform = useMemo(() => {
+  const transform = useMemo(() => {
     let filterByAccount = queries.getAccountFilter(params.id, '_account');
     let filterByPayee = queries.getAccountFilter(
       params.id,
diff --git a/packages/desktop-client/src/components/accounts/AccountSyncCheck.js b/packages/desktop-client/src/components/accounts/AccountSyncCheck.js
index c6e2e4e44..d7d3597b7 100644
--- a/packages/desktop-client/src/components/accounts/AccountSyncCheck.js
+++ b/packages/desktop-client/src/components/accounts/AccountSyncCheck.js
@@ -49,24 +49,24 @@ function getErrorMessage(type, code) {
 }
 
 export default function AccountSyncCheck() {
-  let accounts = useSelector(state => state.queries.accounts);
-  let failedAccounts = useSelector(state => state.account.failedAccounts);
-  let { unlinkAccount, pushModal } = useActions();
+  const accounts = useSelector(state => state.queries.accounts);
+  const failedAccounts = useSelector(state => state.account.failedAccounts);
+  const { unlinkAccount, pushModal } = useActions();
 
-  let { id } = useParams();
-  let [open, setOpen] = useState(false);
+  const { id } = useParams();
+  const [open, setOpen] = useState(false);
   if (!failedAccounts) {
     return null;
   }
 
-  let error = failedAccounts.get(id);
+  const error = failedAccounts.get(id);
   if (!error) {
     return null;
   }
 
-  let account = accounts.find(account => account.id === id);
-  let { type, code } = error;
-  let showAuth =
+  const account = accounts.find(account => account.id === id);
+  const { type, code } = error;
+  const showAuth =
     (type === 'ITEM_ERROR' && code === 'ITEM_LOGIN_REQUIRED') ||
     (type === 'INVALID_INPUT' && code === 'INVALID_ACCESS_TOKEN');
 
diff --git a/packages/desktop-client/src/components/accounts/Balance.js b/packages/desktop-client/src/components/accounts/Balance.js
index c3710c2c9..8383b055c 100644
--- a/packages/desktop-client/src/components/accounts/Balance.js
+++ b/packages/desktop-client/src/components/accounts/Balance.js
@@ -40,9 +40,9 @@ function DetailedBalance({ name, balance, isExactBalance = true }) {
 }
 
 function SelectedBalance({ selectedItems, account }) {
-  let name = `selected-balance-${[...selectedItems].join('-')}`;
+  const name = `selected-balance-${[...selectedItems].join('-')}`;
 
-  let rows = useSheetValue({
+  const rows = useSheetValue({
     name,
     query: q('transactions')
       .filter({
@@ -51,9 +51,9 @@ function SelectedBalance({ selectedItems, account }) {
       })
       .select('id'),
   });
-  let ids = new Set((rows || []).map(r => r.id));
+  const ids = new Set((rows || []).map(r => r.id));
 
-  let finalIds = [...selectedItems].filter(id => !ids.has(id));
+  const finalIds = [...selectedItems].filter(id => !ids.has(id));
   let balance = useSheetValue({
     name: name + '-sum',
     query: q('transactions')
@@ -63,14 +63,14 @@ function SelectedBalance({ selectedItems, account }) {
   });
 
   let scheduleBalance = null;
-  let scheduleData = useCachedSchedules();
-  let schedules = scheduleData ? scheduleData.schedules : [];
-  let previewIds = [...selectedItems]
+  const scheduleData = useCachedSchedules();
+  const schedules = scheduleData ? scheduleData.schedules : [];
+  const previewIds = [...selectedItems]
     .filter(id => isPreviewId(id))
     .map(id => id.slice(8));
   let isExactBalance = true;
 
-  for (let s of schedules) {
+  for (const s of schedules) {
     if (previewIds.includes(s.id)) {
       // If a schedule is `between X and Y` then we calculate the average
       if (s._amountOp === 'isbetween') {
@@ -105,11 +105,11 @@ function SelectedBalance({ selectedItems, account }) {
 }
 
 function MoreBalances({ balanceQuery }) {
-  let cleared = useSheetValue({
+  const cleared = useSheetValue({
     name: balanceQuery.name + '-cleared',
     query: balanceQuery.query.filter({ cleared: true }),
   });
-  let uncleared = useSheetValue({
+  const uncleared = useSheetValue({
     name: balanceQuery.name + '-uncleared',
     query: balanceQuery.query.filter({ cleared: false }),
   });
@@ -128,7 +128,7 @@ export function Balances({
   onToggleExtraBalances,
   account,
 }) {
-  let selectedItems = useSelectedItems();
+  const selectedItems = useSelectedItems();
 
   return (
     <View
diff --git a/packages/desktop-client/src/components/accounts/Header.js b/packages/desktop-client/src/components/accounts/Header.js
index ab40a6368..6e3992583 100644
--- a/packages/desktop-client/src/components/accounts/Header.js
+++ b/packages/desktop-client/src/components/accounts/Header.js
@@ -78,9 +78,9 @@ export function AccountHeader({
   onDeleteFilter,
   onScheduleAction,
 }) {
-  let [menuOpen, setMenuOpen] = useState(false);
-  let searchInput = useRef(null);
-  let splitsExpanded = useSplitsExpanded();
+  const [menuOpen, setMenuOpen] = useState(false);
+  const searchInput = useRef(null);
+  const splitsExpanded = useSplitsExpanded();
 
   let canSync = account && account.account_id;
   if (!account) {
@@ -359,7 +359,7 @@ function AccountMenu({
   onReconcile,
   onMenuSelect,
 }) {
-  let [tooltip, setTooltip] = useState('default');
+  const [tooltip, setTooltip] = useState('default');
   const syncServerStatus = useSyncServerStatus();
 
   return tooltip === 'reconcile' ? (
diff --git a/packages/desktop-client/src/components/accounts/MobileAccount.js b/packages/desktop-client/src/components/accounts/MobileAccount.js
index 794c59a4c..837764310 100644
--- a/packages/desktop-client/src/components/accounts/MobileAccount.js
+++ b/packages/desktop-client/src/components/accounts/MobileAccount.js
@@ -41,13 +41,13 @@ const getSchedulesTransform = memoizeOne((id, hasSearch) => {
 });
 
 function PreviewTransactions({ accountId, children }) {
-  let scheduleData = useCachedSchedules();
+  const scheduleData = useCachedSchedules();
 
   if (scheduleData == null) {
     return children(null);
   }
 
-  let schedules = scheduleData.schedules.filter(
+  const schedules = scheduleData.schedules.filter(
     s =>
       !s.completed &&
       ['due', 'upcoming', 'missed'].includes(scheduleData.statuses.get(s.id)),
@@ -76,15 +76,15 @@ export default function Account(props) {
   const [searchText, setSearchText] = useState('');
   const [currentQuery, setCurrentQuery] = useState();
 
-  let state = useSelector(state => ({
+  const state = useSelector(state => ({
     payees: state.queries.payees,
     newTransactions: state.queries.newTransactions,
     prefs: state.prefs.local,
     dateFormat: state.prefs.local.dateFormat || 'MM/dd/yyyy',
   }));
 
-  let dispatch = useDispatch();
-  let actionCreators = useMemo(
+  const dispatch = useDispatch();
+  const actionCreators = useMemo(
     () => bindActionCreators(actions, dispatch),
     [dispatch],
   );
@@ -106,7 +106,7 @@ export default function Account(props) {
   };
 
   const fetchTransactions = async () => {
-    let query = makeRootQuery();
+    const query = makeRootQuery();
     setCurrentQuery(query);
     updateQuery(query);
   };
@@ -189,9 +189,9 @@ export default function Account(props) {
     }
   };
 
-  let balance = queries.accountBalance(account);
-  let numberFormat = state.prefs.numberFormat || 'comma-dot';
-  let hideFraction = state.prefs.hideFraction || false;
+  const balance = queries.accountBalance(account);
+  const numberFormat = state.prefs.numberFormat || 'comma-dot';
+  const hideFraction = state.prefs.hideFraction || false;
 
   return (
     <SchedulesProvider
diff --git a/packages/desktop-client/src/components/accounts/MobileAccountDetails.js b/packages/desktop-client/src/components/accounts/MobileAccountDetails.js
index b20832df9..c2a250d2b 100644
--- a/packages/desktop-client/src/components/accounts/MobileAccountDetails.js
+++ b/packages/desktop-client/src/components/accounts/MobileAccountDetails.js
@@ -75,7 +75,7 @@ export default function AccountDetails({
   onSelectTransaction,
   pushModal,
 }) {
-  let allTransactions = useMemo(() => {
+  const allTransactions = useMemo(() => {
     return prependTransactions.concat(transactions);
   }, [prependTransactions, transactions]);
 
diff --git a/packages/desktop-client/src/components/accounts/MobileAccounts.js b/packages/desktop-client/src/components/accounts/MobileAccounts.js
index 2df04b5ac..ac71f9231 100644
--- a/packages/desktop-client/src/components/accounts/MobileAccounts.js
+++ b/packages/desktop-client/src/components/accounts/MobileAccounts.js
@@ -216,18 +216,18 @@ function AccountList({
 }
 
 export default function Accounts() {
-  let accounts = useSelector(state => state.queries.accounts);
-  let newTransactions = useSelector(state => state.queries.newTransactions);
-  let updatedAccounts = useSelector(state => state.queries.updatedAccounts);
-  let numberFormat = useSelector(
+  const accounts = useSelector(state => state.queries.accounts);
+  const newTransactions = useSelector(state => state.queries.newTransactions);
+  const updatedAccounts = useSelector(state => state.queries.updatedAccounts);
+  const numberFormat = useSelector(
     state => state.prefs.local.numberFormat || 'comma-dot',
   );
-  let hideFraction = useSelector(
+  const hideFraction = useSelector(
     state => state.prefs.local.hideFraction || false,
   );
 
   const { list: categories } = useCategories();
-  let { getAccounts, replaceModal, syncAndDownload } = useActions();
+  const { getAccounts, replaceModal, syncAndDownload } = useActions();
 
   const transactions = useState({});
   const navigate = useNavigate();
diff --git a/packages/desktop-client/src/components/accounts/Reconcile.js b/packages/desktop-client/src/components/accounts/Reconcile.js
index 762a728f8..d01ad8ef3 100644
--- a/packages/desktop-client/src/components/accounts/Reconcile.js
+++ b/packages/desktop-client/src/components/accounts/Reconcile.js
@@ -20,13 +20,13 @@ export function ReconcilingMessage({
   onDone,
   onCreateTransaction,
 }) {
-  let cleared = useSheetValue({
+  const cleared = useSheetValue({
     name: balanceQuery.name + '-cleared',
     value: 0,
     query: balanceQuery.query.filter({ cleared: true }),
   });
-  let format = useFormat();
-  let targetDiff = targetBalance - cleared;
+  const format = useFormat();
+  const targetDiff = targetBalance - cleared;
 
   return (
     <View
@@ -96,18 +96,18 @@ export function ReconcilingMessage({
 }
 
 export function ReconcileTooltip({ account, onReconcile, onClose }) {
-  let balanceQuery = queries.accountBalance(account);
-  let clearedBalance = useSheetValue({
+  const balanceQuery = queries.accountBalance(account);
+  const clearedBalance = useSheetValue({
     name: balanceQuery.name + '-cleared',
     value: null,
     query: balanceQuery.query.filter({ cleared: true }),
   });
-  let format = useFormat();
+  const format = useFormat();
 
   function onSubmit(e) {
     e.preventDefault();
-    let input = e.target.elements[0];
-    let amount = currencyToInteger(input.value);
+    const input = e.target.elements[0];
+    const amount = currencyToInteger(input.value);
     if (amount != null) {
       onReconcile(amount == null ? clearedBalance : amount);
       onClose();
diff --git a/packages/desktop-client/src/components/autocomplete/Autocomplete.tsx b/packages/desktop-client/src/components/autocomplete/Autocomplete.tsx
index 16491a6fd..5c413b01d 100644
--- a/packages/desktop-client/src/components/autocomplete/Autocomplete.tsx
+++ b/packages/desktop-client/src/components/autocomplete/Autocomplete.tsx
@@ -24,7 +24,7 @@ const inst: { lastChangeType? } = {};
 
 function findItem(strict, suggestions, value) {
   if (strict) {
-    let idx = suggestions.findIndex(item => item.id === value);
+    const idx = suggestions.findIndex(item => item.id === value);
     return idx === -1 ? null : suggestions[idx];
   }
 
@@ -70,7 +70,7 @@ function fireUpdate(onUpdate, strict, suggestions, index, value) {
   } else {
     if (index == null) {
       // If passing in a value directly, validate the id
-      let sug = suggestions.find(sug => sug.id === value);
+      const sug = suggestions.find(sug => sug.id === value);
       if (sug) {
         selected = sug.id;
       }
@@ -90,7 +90,7 @@ function defaultRenderItems(items, getItemProps, highlightedIndex) {
   return (
     <div>
       {items.map((item, index) => {
-        let name = getItemName(item);
+        const name = getItemName(item);
         return (
           <div
             {...getItemProps({ item })}
@@ -222,7 +222,7 @@ function SingleAutocomplete({
 
   function resetState(newValue) {
     const val = newValue === undefined ? initialValue : newValue;
-    let selectedItem = findItem(strict, suggestions, val);
+    const selectedItem = findItem(strict, suggestions, val);
 
     setSelectedItem(selectedItem);
     setValue(selectedItem ? getItemName(selectedItem) : '');
@@ -311,10 +311,10 @@ function SingleAutocomplete({
 
           setHighlightedIndex(null);
         } else {
-          let defaultGetHighlightedIndex = filteredSuggestions => {
+          const defaultGetHighlightedIndex = filteredSuggestions => {
             return highlightFirst && filteredSuggestions.length ? 0 : null;
           };
-          let highlightedIndex = (
+          const highlightedIndex = (
             getHighlightedIndex || defaultGetHighlightedIndex
           )(filteredSuggestions);
           // @ts-expect-error Types say there is no type
@@ -415,7 +415,7 @@ function SingleAutocomplete({
 
                   // If not using table behavior, reset the input on blur. Tables
                   // handle saving the value on blur.
-                  let value = selectedItem ? getItemId(selectedItem) : null;
+                  const value = selectedItem ? getItemId(selectedItem) : null;
 
                   resetState(value);
                 } else {
@@ -423,7 +423,7 @@ function SingleAutocomplete({
                 }
               },
               onKeyDown: (e: KeyboardEvent<HTMLInputElement>) => {
-                let { onKeyDown } = inputProps || {};
+                const { onKeyDown } = inputProps || {};
 
                 // If the dropdown is open, an item is highlighted, and the user
                 // pressed enter, always capture that and handle it ourselves
@@ -561,15 +561,15 @@ function MultiAutocomplete({
   strict,
   ...props
 }: MultiAutocompleteProps) {
-  let [focused, setFocused] = useState(false);
-  let lastSelectedItems = useRef<unknown[]>();
+  const [focused, setFocused] = useState(false);
+  const lastSelectedItems = useRef<unknown[]>();
 
   useEffect(() => {
     lastSelectedItems.current = selectedItems;
   });
 
   function onRemoveItem(id) {
-    let items = selectedItems.filter(i => i !== id);
+    const items = selectedItems.filter(i => i !== id);
     onSelect(items);
   }
 
diff --git a/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
index 59c71f81c..b8c07ba36 100644
--- a/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
+++ b/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
@@ -117,7 +117,7 @@ export default function CategoryAutocomplete({
   renderCategoryItem,
   ...props
 }: CategoryAutocompleteProps) {
-  let categorySuggestions: Array<
+  const categorySuggestions: Array<
     CategoryEntity & { group?: CategoryGroupEntity }
   > = useMemo(
     () =>
diff --git a/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx
index 740cd93eb..6ed812c7b 100644
--- a/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx
+++ b/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx
@@ -68,7 +68,7 @@ function PayeeList({
   renderPayeeItem = defaultRenderPayeeItem,
   footer,
 }) {
-  let isFiltered = items.filtered;
+  const isFiltered = items.filtered;
   let createNew = null;
   items = [...items];
 
@@ -76,12 +76,12 @@ function PayeeList({
   // with the value of the input so it always shows whatever the user
   // entered
   if (items[0].id === 'new') {
-    let [first, ...rest] = items;
+    const [first, ...rest] = items;
     createNew = first;
     items = rest;
   }
 
-  let offset = createNew ? 1 : 0;
+  const offset = createNew ? 1 : 0;
   let lastType = null;
 
   return (
@@ -102,14 +102,14 @@ function PayeeList({
           })}
 
         {items.map((item, idx) => {
-          let type = item.transfer_acct ? 'account' : 'payee';
+          const type = item.transfer_acct ? 'account' : 'payee';
           let title;
           if (type === 'payee' && lastType !== type) {
             title = 'Payees';
           } else if (type === 'account' && lastType !== type) {
             title = 'Transfer To/From';
           }
-          let showMoreMessage = idx === items.length - 1 && isFiltered;
+          const showMoreMessage = idx === items.length - 1 && isFiltered;
           lastType = type;
 
           return (
@@ -185,20 +185,20 @@ export default function PayeeAutocomplete({
   payees,
   ...props
 }: PayeeAutocompleteProps) {
-  let cachedPayees = useCachedPayees();
+  const cachedPayees = useCachedPayees();
   if (!payees) {
     payees = cachedPayees;
   }
 
-  let cachedAccounts = useCachedAccounts();
+  const cachedAccounts = useCachedAccounts();
   if (!accounts) {
     accounts = cachedAccounts;
   }
 
-  let [focusTransferPayees, setFocusTransferPayees] = useState(false);
-  let [rawPayee, setRawPayee] = useState('');
-  let hasPayeeInput = !!rawPayee;
-  let payeeSuggestions = useMemo(() => {
+  const [focusTransferPayees, setFocusTransferPayees] = useState(false);
+  const [rawPayee, setRawPayee] = useState('');
+  const hasPayeeInput = !!rawPayee;
+  const payeeSuggestions = useMemo(() => {
     const suggestions = getPayeeSuggestions(
       payees,
       focusTransferPayees,
@@ -211,13 +211,13 @@ export default function PayeeAutocomplete({
     return [{ id: 'new', name: '' }, ...suggestions];
   }, [payees, focusTransferPayees, accounts, hasPayeeInput]);
 
-  let dispatch = useDispatch();
+  const dispatch = useDispatch();
 
   async function handleSelect(value, rawInputValue) {
     if (tableBehavior) {
       onSelect?.(makeNew(value, rawInputValue));
     } else {
-      let create = () => dispatch(createPayee(rawInputValue));
+      const create = () => dispatch(createPayee(rawInputValue));
 
       if (Array.isArray(value)) {
         value = await Promise.all(value.map(v => (v === 'new' ? create() : v)));
@@ -279,10 +279,10 @@ export default function PayeeAutocomplete({
         });
 
         filtered.sort((p1, p2) => {
-          let r1 = p1.name.toLowerCase().startsWith(value.toLowerCase());
-          let r2 = p2.name.toLowerCase().startsWith(value.toLowerCase());
-          let r1exact = p1.name.toLowerCase() === value.toLowerCase();
-          let r2exact = p2.name.toLowerCase() === value.toLowerCase();
+          const r1 = p1.name.toLowerCase().startsWith(value.toLowerCase());
+          const r2 = p2.name.toLowerCase().startsWith(value.toLowerCase());
+          const r1exact = p1.name.toLowerCase() === value.toLowerCase();
+          const r2exact = p2.name.toLowerCase() === value.toLowerCase();
 
           // (maniacal laughter) mwahaHAHAHAHAH
           if (p1.id === 'new') {
@@ -306,7 +306,7 @@ export default function PayeeAutocomplete({
           }
         });
 
-        let isf = filtered.length > 100;
+        const isf = filtered.length > 100;
         filtered = filtered.slice(0, 100);
         filtered.filtered = isf;
 
diff --git a/packages/desktop-client/src/components/autocomplete/SavedFilterAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/SavedFilterAutocomplete.tsx
index 347db0826..a2800b856 100644
--- a/packages/desktop-client/src/components/autocomplete/SavedFilterAutocomplete.tsx
+++ b/packages/desktop-client/src/components/autocomplete/SavedFilterAutocomplete.tsx
@@ -63,7 +63,7 @@ export default function SavedFilterAutocomplete({
   embedded,
   ...props
 }: SavedFilterAutocompleteProps) {
-  let filters = useFilters() || [];
+  const filters = useFilters() || [];
 
   return (
     <Autocomplete
diff --git a/packages/desktop-client/src/components/budget/BalanceWithCarryover.tsx b/packages/desktop-client/src/components/budget/BalanceWithCarryover.tsx
index f0c29ee52..7b09d547d 100644
--- a/packages/desktop-client/src/components/budget/BalanceWithCarryover.tsx
+++ b/packages/desktop-client/src/components/budget/BalanceWithCarryover.tsx
@@ -29,11 +29,11 @@ export default function BalanceWithCarryover({
   balanceStyle,
   carryoverStyle,
 }: BalanceWithCarryoverProps) {
-  let carryoverValue = useSheetValue(carryover);
-  let balanceValue = useSheetValue(balance);
-  let goalValue = useSheetValue(goal);
-  let budgetedValue = useSheetValue(budgeted);
-  let isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
+  const carryoverValue = useSheetValue(carryover);
+  const balanceValue = useSheetValue(balance);
+  const goalValue = useSheetValue(goal);
+  const budgetedValue = useSheetValue(budgeted);
+  const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
   return (
     <View style={style}>
       <CellValue
diff --git a/packages/desktop-client/src/components/budget/BudgetCategories.js b/packages/desktop-client/src/components/budget/BudgetCategories.js
index 9f6d2286f..e4788008c 100644
--- a/packages/desktop-client/src/components/budget/BudgetCategories.js
+++ b/packages/desktop-client/src/components/budget/BudgetCategories.js
@@ -39,8 +39,8 @@ const BudgetCategories = memo(
     onShowNewGroup,
     onHideNewGroup,
   }) => {
-    let items = useMemo(() => {
-      let [expenseGroups, incomeGroup] = separateGroups(categoryGroups);
+    const items = useMemo(() => {
+      const [expenseGroups, incomeGroup] = separateGroups(categoryGroups);
 
       let items = Array.prototype.concat.apply(
         [],
@@ -53,7 +53,7 @@ const BudgetCategories = memo(
             cat => showHiddenCategories || !cat.hidden,
           );
 
-          let items = [{ type: 'expense-group', value: { ...group } }];
+          const items = [{ type: 'expense-group', value: { ...group } }];
 
           if (newCategoryForGroup === group.id) {
             items.push({ type: 'new-category' });
@@ -103,13 +103,13 @@ const BudgetCategories = memo(
       showHiddenCategories,
     ]);
 
-    let [dragState, setDragState] = useState(null);
-    let [savedCollapsed, setSavedCollapsed] = useState(null);
+    const [dragState, setDragState] = useState(null);
+    const [savedCollapsed, setSavedCollapsed] = useState(null);
 
     // TODO: If we turn this into a reducer, we could probably memoize
     // each item in the list for better perf
     function onDragChange(newDragState) {
-      let { state } = newDragState;
+      const { state } = newDragState;
 
       if (state === 'start-preview') {
         setDragState({
@@ -283,7 +283,7 @@ const BudgetCategories = memo(
               throw new Error('Unknown item type: ' + item.type);
           }
 
-          let pos =
+          const pos =
             idx === 0 ? 'first' : idx === items.length - 1 ? 'last' : null;
 
           return (
diff --git a/packages/desktop-client/src/components/budget/BudgetMonthCountContext.tsx b/packages/desktop-client/src/components/budget/BudgetMonthCountContext.tsx
index 4a825f4ec..a69e40fb6 100644
--- a/packages/desktop-client/src/components/budget/BudgetMonthCountContext.tsx
+++ b/packages/desktop-client/src/components/budget/BudgetMonthCountContext.tsx
@@ -12,7 +12,8 @@ type BudgetMonthCountContextValue = {
   setDisplayMax: Dispatch<SetStateAction<number>>;
 };
 
-let BudgetMonthCountContext = createContext<BudgetMonthCountContextValue>(null);
+const BudgetMonthCountContext =
+  createContext<BudgetMonthCountContextValue>(null);
 
 type BudgetMonthCountProviderProps = {
   children: ReactNode;
@@ -21,7 +22,7 @@ type BudgetMonthCountProviderProps = {
 export function BudgetMonthCountProvider({
   children,
 }: BudgetMonthCountProviderProps) {
-  let [displayMax, setDisplayMax] = useState(1);
+  const [displayMax, setDisplayMax] = useState(1);
 
   return (
     <BudgetMonthCountContext.Provider value={{ displayMax, setDisplayMax }}>
diff --git a/packages/desktop-client/src/components/budget/BudgetPageHeader.tsx b/packages/desktop-client/src/components/budget/BudgetPageHeader.tsx
index c5f3576c7..919793bc3 100644
--- a/packages/desktop-client/src/components/budget/BudgetPageHeader.tsx
+++ b/packages/desktop-client/src/components/budget/BudgetPageHeader.tsx
@@ -17,8 +17,8 @@ type BudgetPageHeaderProps = {
 const BudgetPageHeader = memo<BudgetPageHeaderProps>(
   ({ startMonth, onMonthSelect, numMonths, monthBounds }) => {
     function getValidMonth(month) {
-      let start = monthBounds.start;
-      let end = monthUtils.subMonths(monthBounds.end, numMonths - 1);
+      const start = monthBounds.start;
+      const end = monthUtils.subMonths(monthBounds.end, numMonths - 1);
 
       if (month < start) {
         return start;
diff --git a/packages/desktop-client/src/components/budget/BudgetSummaries.tsx b/packages/desktop-client/src/components/budget/BudgetSummaries.tsx
index 11dc77f5b..1367005cc 100644
--- a/packages/desktop-client/src/components/budget/BudgetSummaries.tsx
+++ b/packages/desktop-client/src/components/budget/BudgetSummaries.tsx
@@ -25,37 +25,37 @@ type BudgetSummariesProps = {
 export default function BudgetSummaries({
   SummaryComponent,
 }: BudgetSummariesProps) {
-  let { months } = useContext(MonthsContext);
+  const { months } = useContext(MonthsContext);
 
-  let [widthState, setWidthState] = useState(0);
-  let [styles, spring] = useSpring(() => ({
+  const [widthState, setWidthState] = useState(0);
+  const [styles, spring] = useSpring(() => ({
     x: 0,
     config: { mass: 3, tension: 600, friction: 80 },
   }));
 
-  let containerRef = useResizeObserver(
+  const containerRef = useResizeObserver(
     useCallback(rect => {
       setWidthState(rect.width);
     }, []),
   );
 
-  let prevMonth0 = useRef(months[0]);
-  let allMonths = [...months];
+  const prevMonth0 = useRef(months[0]);
+  const allMonths = [...months];
   allMonths.unshift(subMonths(months[0], 1));
   allMonths.push(addMonths(months[months.length - 1], 1));
-  let monthWidth = widthState / months.length;
+  const monthWidth = widthState / months.length;
 
   useLayoutEffect(() => {
-    let prevMonth = prevMonth0.current;
-    let reversed = prevMonth > months[0];
-    let offsetX = monthWidth;
+    const prevMonth = prevMonth0.current;
+    const reversed = prevMonth > months[0];
+    const offsetX = monthWidth;
     let from = reversed ? -offsetX * 2 : 0;
 
     if (prevMonth !== allMonths[0] && prevMonth !== allMonths[2]) {
       from = -offsetX;
     }
 
-    let to = -offsetX;
+    const to = -offsetX;
     spring.start({ from: { x: from }, x: to });
   }, [months[0]]);
 
diff --git a/packages/desktop-client/src/components/budget/BudgetTable.js b/packages/desktop-client/src/components/budget/BudgetTable.js
index 46568a288..1059c0633 100644
--- a/packages/desktop-client/src/components/budget/BudgetTable.js
+++ b/packages/desktop-client/src/components/budget/BudgetTable.js
@@ -33,16 +33,20 @@ class BudgetTable extends Component {
   };
 
   onReorderCategory = (id, dropPos, targetId) => {
-    let { categoryGroups } = this.props;
+    const { categoryGroups } = this.props;
 
-    let isGroup = !!categoryGroups.find(g => g.id === targetId);
+    const isGroup = !!categoryGroups.find(g => g.id === targetId);
 
     if (isGroup) {
-      let { targetId: groupId } = findSortUp(categoryGroups, dropPos, targetId);
-      let group = categoryGroups.find(g => g.id === groupId);
+      const { targetId: groupId } = findSortUp(
+        categoryGroups,
+        dropPos,
+        targetId,
+      );
+      const group = categoryGroups.find(g => g.id === groupId);
 
       if (group) {
-        let { categories } = group;
+        const { categories } = group;
         this.props.onReorderCategory({
           id,
           groupId: group.id,
@@ -55,7 +59,7 @@ class BudgetTable extends Component {
     } else {
       let targetGroup;
 
-      for (let group of categoryGroups) {
+      for (const group of categoryGroups) {
         if (group.categories.find(cat => cat.id === targetId)) {
           targetGroup = group;
           break;
@@ -71,7 +75,7 @@ class BudgetTable extends Component {
   };
 
   onReorderGroup = (id, dropPos, targetId) => {
-    let { categoryGroups } = this.props;
+    const { categoryGroups } = this.props;
 
     this.props.onReorderGroup({
       id,
@@ -80,8 +84,8 @@ class BudgetTable extends Component {
   };
 
   moveVertically = dir => {
-    let { editing } = this.state;
-    let { type, categoryGroups, collapsed } = this.props;
+    const { editing } = this.state;
+    const { type, categoryGroups, collapsed } = this.props;
 
     const flattened = categoryGroups.reduce((all, group) => {
       if (collapsed.includes(group.id)) {
@@ -151,12 +155,12 @@ class BudgetTable extends Component {
   };
 
   collapseAllCategories = () => {
-    let { setCollapsed, categoryGroups } = this.props;
+    const { setCollapsed, categoryGroups } = this.props;
     setCollapsed(categoryGroups.map(g => g.id));
   };
 
   render() {
-    let {
+    const {
       type,
       categoryGroups,
       prewarmStartMonth,
@@ -177,7 +181,7 @@ class BudgetTable extends Component {
       onShowNewGroup,
       onHideNewGroup,
     } = this.props;
-    let { editing, draggingState, showHiddenCategories } = this.state;
+    const { editing, draggingState, showHiddenCategories } = this.state;
 
     return (
       <View
diff --git a/packages/desktop-client/src/components/budget/DynamicBudgetTable.tsx b/packages/desktop-client/src/components/budget/DynamicBudgetTable.tsx
index 51ab9df27..961f2ee14 100644
--- a/packages/desktop-client/src/components/budget/DynamicBudgetTable.tsx
+++ b/packages/desktop-client/src/components/budget/DynamicBudgetTable.tsx
@@ -10,7 +10,7 @@ import BudgetPageHeader from './BudgetPageHeader';
 import BudgetTable from './BudgetTable';
 
 function getNumPossibleMonths(width: number) {
-  let estimatedTableWidth = width - 200;
+  const estimatedTableWidth = width - 200;
 
   if (estimatedTableWidth < 500) {
     return 1;
@@ -51,13 +51,13 @@ const DynamicBudgetTableInner = forwardRef<
     },
     ref,
   ) => {
-    let prefs = useSelector(state => state.prefs.local);
-    let { setDisplayMax } = useBudgetMonthCount();
-    let actions = useActions();
+    const prefs = useSelector(state => state.prefs.local);
+    const { setDisplayMax } = useBudgetMonthCount();
+    const actions = useActions();
 
-    let numPossible = getNumPossibleMonths(width);
-    let numMonths = Math.min(numPossible, maxMonths);
-    let maxWidth = 200 + 500 * numMonths;
+    const numPossible = getNumPossibleMonths(width);
+    const numMonths = Math.min(numPossible, maxMonths);
+    const maxWidth = 200 + 500 * numMonths;
 
     useEffect(() => {
       setDisplayMax(numPossible);
diff --git a/packages/desktop-client/src/components/budget/ExpenseCategory.tsx b/packages/desktop-client/src/components/budget/ExpenseCategory.tsx
index af20de7e5..cc1313966 100644
--- a/packages/desktop-client/src/components/budget/ExpenseCategory.tsx
+++ b/packages/desktop-client/src/components/budget/ExpenseCategory.tsx
@@ -52,14 +52,14 @@ function ExpenseCategory({
     dragging = true;
   }
 
-  let { dragRef } = useDraggable({
+  const { dragRef } = useDraggable({
     type: 'category',
     onDragChange,
     item: cat,
     canDrag: editingCell === null,
   });
 
-  let { dropRef, dropPos } = useDroppable({
+  const { dropRef, dropPos } = useDroppable({
     types: 'category',
     id: cat.id,
     onDrop: onReorder,
diff --git a/packages/desktop-client/src/components/budget/ExpenseGroup.tsx b/packages/desktop-client/src/components/budget/ExpenseGroup.tsx
index 6104e0125..7c1bfd898 100644
--- a/packages/desktop-client/src/components/budget/ExpenseGroup.tsx
+++ b/packages/desktop-client/src/components/budget/ExpenseGroup.tsx
@@ -48,22 +48,22 @@ function ExpenseGroup({
   onToggleCollapse,
   onShowNewCategory,
 }: ExpenseGroupProps) {
-  let dragging = dragState && dragState.item === group;
+  const dragging = dragState && dragState.item === group;
 
-  let { dragRef } = useDraggable({
+  const { dragRef } = useDraggable({
     type: 'group',
     onDragChange,
     item: group,
     canDrag: editingCell === null,
   });
 
-  let { dropRef, dropPos } = useDroppable({
+  const { dropRef, dropPos } = useDroppable({
     types: 'group',
     id: group.id,
     onDrop: onReorderGroup,
   });
 
-  let { dropRef: catDropRef, dropPos: catDropPos } = useDroppable({
+  const { dropRef: catDropRef, dropPos: catDropPos } = useDroppable({
     types: 'category',
     id: group.id,
     onDrop: onReorderCategory,
diff --git a/packages/desktop-client/src/components/budget/IncomeCategory.tsx b/packages/desktop-client/src/components/budget/IncomeCategory.tsx
index 110da5523..0d5625186 100644
--- a/packages/desktop-client/src/components/budget/IncomeCategory.tsx
+++ b/packages/desktop-client/src/components/budget/IncomeCategory.tsx
@@ -43,14 +43,14 @@ function IncomeCategory({
   onReorder,
   onShowActivity,
 }: IncomeCategoryProps) {
-  let { dragRef } = useDraggable({
+  const { dragRef } = useDraggable({
     type: 'income-category',
     onDragChange,
     item: cat,
     canDrag: editingCell === null,
   });
 
-  let { dropRef, dropPos } = useDroppable({
+  const { dropRef, dropPos } = useDroppable({
     types: 'income-category',
     id: cat.id,
     onDrop: onReorder,
diff --git a/packages/desktop-client/src/components/budget/MobileBudget.js b/packages/desktop-client/src/components/budget/MobileBudget.js
index 4f9e1601c..8c3e7327c 100644
--- a/packages/desktop-client/src/components/budget/MobileBudget.js
+++ b/packages/desktop-client/src/components/budget/MobileBudget.js
@@ -41,7 +41,7 @@ class Budget extends Component {
   }
 
   async loadCategories() {
-    let result = await this.props.getCategories();
+    const result = await this.props.getCategories();
     this.setState({ categoryGroups: result.grouped });
   }
 
@@ -63,7 +63,7 @@ class Budget extends Component {
 
     this.setState({ initialized: true });
 
-    let unlisten = listen('sync-event', ({ type, tables }) => {
+    const unlisten = listen('sync-event', ({ type, tables }) => {
       if (
         type === 'success' &&
         (tables.includes('categories') ||
@@ -145,14 +145,14 @@ class Budget extends Component {
   };
 
   onDeleteGroup = async groupId => {
-    let group = this.state.categoryGroups?.find(g => g.id === groupId);
+    const group = this.state.categoryGroups?.find(g => g.id === groupId);
 
     if (!group) {
       return;
     }
 
     let mustTransfer = false;
-    for (let category of group.categories) {
+    for (const category of group.categories) {
       if (await send('must-category-transfer', { id: category.id })) {
         mustTransfer = true;
         break;
@@ -210,21 +210,22 @@ class Budget extends Component {
   };
 
   onReorderCategory = (id, { inGroup, aroundCategory }) => {
-    let { categoryGroups } = this.state;
+    const { categoryGroups } = this.state;
     let groupId, targetId;
 
     if (inGroup) {
       groupId = inGroup;
     } else if (aroundCategory) {
-      let { id: catId, position } = aroundCategory;
+      const { id: originalCatId, position } = aroundCategory;
 
-      let group = categoryGroups.find(group =>
+      let catId = originalCatId;
+      const group = categoryGroups.find(group =>
         group.categories.find(cat => cat.id === catId),
       );
 
       if (position === 'bottom') {
-        let { categories } = group;
-        let idx = categories.findIndex(cat => cat.id === catId);
+        const { categories } = group;
+        const idx = categories.findIndex(cat => cat.id === catId);
         catId = idx < categories.length - 1 ? categories[idx + 1].id : null;
       }
 
@@ -240,10 +241,10 @@ class Budget extends Component {
   };
 
   onReorderGroup = (id, targetId, position) => {
-    let { categoryGroups } = this.state;
+    const { categoryGroups } = this.state;
 
     if (position === 'bottom') {
-      let idx = categoryGroups.findIndex(group => group.id === targetId);
+      const idx = categoryGroups.findIndex(group => group.id === targetId);
       targetId =
         idx < categoryGroups.length - 1 ? categoryGroups[idx + 1].id : null;
     }
@@ -266,23 +267,23 @@ class Budget extends Component {
   };
 
   onPrevMonth = async () => {
-    let { spreadsheet, budgetType } = this.props;
-    let month = monthUtils.subMonths(this.state.currentMonth, 1);
+    const { spreadsheet, budgetType } = this.props;
+    const month = monthUtils.subMonths(this.state.currentMonth, 1);
     await prewarmMonth(budgetType, spreadsheet, month);
     this.setState({ currentMonth: month, initialized: true });
   };
 
   onNextMonth = async () => {
-    let { spreadsheet, budgetType } = this.props;
-    let month = monthUtils.addMonths(this.state.currentMonth, 1);
+    const { spreadsheet, budgetType } = this.props;
+    const month = monthUtils.addMonths(this.state.currentMonth, 1);
     await prewarmMonth(budgetType, spreadsheet, month);
     this.setState({ currentMonth: month, initialized: true });
   };
 
   onOpenActionSheet = () => {
-    let { budgetType } = this.props;
+    const { budgetType } = this.props;
 
-    let options = [
+    const options = [
       'Edit Categories',
       'Copy last month’s budget',
       'Set budgets to zero',
@@ -352,8 +353,8 @@ class Budget extends Component {
       applyBudgetAction,
       pushModal,
     } = this.props;
-    let numberFormat = prefs.numberFormat || 'comma-dot';
-    let hideFraction = prefs.hideFraction || false;
+    const numberFormat = prefs.numberFormat || 'comma-dot';
+    const hideFraction = prefs.hideFraction || false;
 
     if (!categoryGroups || !initialized) {
       return (
@@ -414,14 +415,14 @@ class Budget extends Component {
 }
 
 export default function BudgetWrapper() {
-  let { list: categories, grouped: categoryGroups } = useCategories();
-  let budgetType = useSelector(
+  const { list: categories, grouped: categoryGroups } = useCategories();
+  const budgetType = useSelector(
     state => state.prefs.local.budgetType || 'rollover',
   );
-  let prefs = useSelector(state => state.prefs.local);
+  const prefs = useSelector(state => state.prefs.local);
 
-  let actions = useActions();
-  let spreadsheet = useSpreadsheet();
+  const actions = useActions();
+  const spreadsheet = useSpreadsheet();
   useSetThemeColor(theme.mobileViewTheme);
   return (
     <Budget
diff --git a/packages/desktop-client/src/components/budget/MobileBudgetTable.js b/packages/desktop-client/src/components/budget/MobileBudgetTable.js
index 0190840d5..4f8e81107 100644
--- a/packages/desktop-client/src/components/budget/MobileBudgetTable.js
+++ b/packages/desktop-client/src/components/budget/MobileBudgetTable.js
@@ -40,7 +40,7 @@ import RolloverBudgetBalanceTooltip from './rollover/BalanceTooltip';
 import { makeAmountGrey } from './util';
 
 function ToBudget({ toBudget, onClick }) {
-  let amount = useSheetValue(toBudget);
+  const amount = useSheetValue(toBudget);
   return (
     <Button
       type="bare"
@@ -70,12 +70,12 @@ function ToBudget({ toBudget, onClick }) {
 }
 
 function Saved({ projected, onClick }) {
-  let binding = projected
+  const binding = projected
     ? reportBudget.totalBudgetedSaved
     : reportBudget.totalSaved;
 
-  let saved = useSheetValue(binding) || 0;
-  let isNegative = saved < 0;
+  const saved = useSheetValue(binding) || 0;
+  const isNegative = saved < 0;
 
   return (
     <Button
@@ -135,7 +135,7 @@ function BudgetCell({
   onEdit,
   isEditing,
 }) {
-  let sheetValue = useSheetValue(binding);
+  const sheetValue = useSheetValue(binding);
 
   function updateBudgetAmount(amount) {
     onBudgetAction?.(month, 'budget-amount', {
@@ -255,14 +255,14 @@ const ExpenseCategory = memo(function ExpenseCategory({
   show3Cols,
   showBudgetedCol,
 }) {
-  let opacity = blank ? 0 : 1;
-  let showEditables = editMode || isEditing;
+  const opacity = blank ? 0 : 1;
+  const showEditables = editMode || isEditing;
 
-  let [categoryName, setCategoryName] = useState(category.name);
-  let [isHidden, setIsHidden] = useState(category.hidden);
+  const [categoryName, setCategoryName] = useState(category.name);
+  const [isHidden, setIsHidden] = useState(category.hidden);
 
-  let tooltip = useTooltip();
-  let balanceTooltip = useTooltip();
+  const tooltip = useTooltip();
+  const balanceTooltip = useTooltip();
 
   useEffect(() => {
     if (isBudgetActionMenuOpen) {
@@ -276,7 +276,7 @@ const ExpenseCategory = memo(function ExpenseCategory({
     }
   }, [isEditing, tooltip]);
 
-  let onSubmit = () => {
+  const onSubmit = () => {
     if (categoryName) {
       onSave?.({
         ...category,
@@ -288,7 +288,7 @@ const ExpenseCategory = memo(function ExpenseCategory({
     onEdit?.(null);
   };
 
-  let onMenuSelect = type => {
+  const onMenuSelect = type => {
     onEdit?.(null);
     switch (type) {
       case 'toggle-visibility':
@@ -306,10 +306,10 @@ const ExpenseCategory = memo(function ExpenseCategory({
     }
   };
 
-  let listItemRef = useRef();
-  let inputRef = useRef();
+  const listItemRef = useRef();
+  const inputRef = useRef();
 
-  let _onBudgetAction = (monthIndex, action, arg) => {
+  const _onBudgetAction = (monthIndex, action, arg) => {
     onBudgetAction?.(
       monthUtils.getMonthFromIndex(monthUtils.getYear(month), monthIndex),
       action,
@@ -317,7 +317,7 @@ const ExpenseCategory = memo(function ExpenseCategory({
     );
   };
 
-  let content = (
+  const content = (
     <ListItem
       style={{
         backgroundColor: isEditingBudget
@@ -555,13 +555,13 @@ const ExpenseGroupTotals = memo(function ExpenseGroupTotals({
   show3Cols,
   showBudgetedCol,
 }) {
-  let opacity = blank ? 0 : 1;
-  let showEditables = editMode || isEditing;
+  const opacity = blank ? 0 : 1;
+  const showEditables = editMode || isEditing;
 
-  let [groupName, setGroupName] = useState(group.name);
-  let [isHidden, setIsHidden] = useState(group.hidden);
+  const [groupName, setGroupName] = useState(group.name);
+  const [isHidden, setIsHidden] = useState(group.hidden);
 
-  let tooltip = useTooltip();
+  const tooltip = useTooltip();
 
   useEffect(() => {
     if (!isEditing && tooltip.isOpen) {
@@ -569,7 +569,7 @@ const ExpenseGroupTotals = memo(function ExpenseGroupTotals({
     }
   }, [isEditing]);
 
-  let onSubmit = () => {
+  const onSubmit = () => {
     if (groupName) {
       onSave?.({
         ...group,
@@ -581,7 +581,7 @@ const ExpenseGroupTotals = memo(function ExpenseGroupTotals({
     onEdit?.(null);
   };
 
-  let onMenuSelect = type => {
+  const onMenuSelect = type => {
     onEdit?.(null);
     switch (type) {
       case 'add-category':
@@ -602,10 +602,10 @@ const ExpenseGroupTotals = memo(function ExpenseGroupTotals({
     }
   };
 
-  let listItemRef = useRef();
-  let inputRef = useRef();
+  const listItemRef = useRef();
+  const inputRef = useRef();
 
-  let content = (
+  const content = (
     <ListItem
       style={{
         flexDirection: 'row',
@@ -811,11 +811,11 @@ const IncomeGroupTotals = memo(function IncomeGroupTotals({
   isEditing,
   onEdit,
 }) {
-  let [groupName, setGroupName] = useState(group.name);
-  let [isHidden, setIsHidden] = useState(group.hidden);
-  let showEditables = editMode || isEditing;
+  const [groupName, setGroupName] = useState(group.name);
+  const [isHidden, setIsHidden] = useState(group.hidden);
+  const showEditables = editMode || isEditing;
 
-  let tooltip = useTooltip();
+  const tooltip = useTooltip();
 
   useEffect(() => {
     if (!isEditing && tooltip.isOpen) {
@@ -823,7 +823,7 @@ const IncomeGroupTotals = memo(function IncomeGroupTotals({
     }
   }, [isEditing]);
 
-  let onSubmit = () => {
+  const onSubmit = () => {
     if (groupName) {
       onSave?.({
         ...group,
@@ -835,7 +835,7 @@ const IncomeGroupTotals = memo(function IncomeGroupTotals({
     onEdit?.(null);
   };
 
-  let onMenuSelect = type => {
+  const onMenuSelect = type => {
     onEdit?.(null);
     switch (type) {
       case 'add-category':
@@ -856,8 +856,8 @@ const IncomeGroupTotals = memo(function IncomeGroupTotals({
     }
   };
 
-  let listItemRef = useRef();
-  let inputRef = useRef();
+  const listItemRef = useRef();
+  const inputRef = useRef();
 
   return (
     <ListItem
@@ -1019,11 +1019,11 @@ const IncomeCategory = memo(function IncomeCategory({
   isEditingBudget,
   onEditBudget,
 }) {
-  let [categoryName, setCategoryName] = useState(category.name);
-  let [isHidden, setIsHidden] = useState(category.hidden);
-  let showEditables = editMode || isEditing;
+  const [categoryName, setCategoryName] = useState(category.name);
+  const [isHidden, setIsHidden] = useState(category.hidden);
+  const showEditables = editMode || isEditing;
 
-  let tooltip = useTooltip();
+  const tooltip = useTooltip();
 
   useEffect(() => {
     if (!isEditing && tooltip.isOpen) {
@@ -1031,7 +1031,7 @@ const IncomeCategory = memo(function IncomeCategory({
     }
   }, [isEditing]);
 
-  let onSubmit = () => {
+  const onSubmit = () => {
     if (categoryName) {
       onSave?.({
         ...category,
@@ -1043,7 +1043,7 @@ const IncomeCategory = memo(function IncomeCategory({
     onEdit?.(null);
   };
 
-  let onMenuSelect = type => {
+  const onMenuSelect = type => {
     onEdit?.(null);
     switch (type) {
       case 'toggle-visibility':
@@ -1061,8 +1061,8 @@ const IncomeCategory = memo(function IncomeCategory({
     }
   };
 
-  let listItemRef = useRef();
-  let inputRef = useRef();
+  const listItemRef = useRef();
+  const inputRef = useRef();
 
   return (
     <ListItem
@@ -1694,7 +1694,7 @@ export function BudgetTable(props) {
   const show3Cols = width >= 360;
 
   // let editMode = false; // neuter editMode -- sorry, not rewriting drag-n-drop right now
-  let format = useFormat();
+  const format = useFormat();
 
   const mobileShowBudgetedColPref = useSelector(state => {
     return state.prefs?.local?.toggleMobileDisplayPref || true;
@@ -1704,7 +1704,7 @@ export function BudgetTable(props) {
     return state.prefs?.local?.['budget.showHiddenCategories'] || false;
   });
 
-  let [showBudgetedCol, setShowBudgetedCol] = useState(
+  const [showBudgetedCol, setShowBudgetedCol] = useState(
     !mobileShowBudgetedColPref &&
       !document.cookie.match(/mobileShowBudgetedColPref=true/),
   );
@@ -1716,7 +1716,7 @@ export function BudgetTable(props) {
     }
   }
 
-  let buttonStyle = {
+  const buttonStyle = {
     padding: 0,
     backgroundColor: 'transparent',
     borderRadius: 'unset',
@@ -1995,10 +1995,10 @@ function BudgetMenu({
   onToggleHiddenCategories,
   onSwitchBudgetType,
 }) {
-  let tooltip = useTooltip();
-  let isReportBudgetEnabled = useFeatureFlag('reportBudget');
+  const tooltip = useTooltip();
+  const isReportBudgetEnabled = useFeatureFlag('reportBudget');
 
-  let onMenuSelect = name => {
+  const onMenuSelect = name => {
     tooltip.close();
     switch (name) {
       case 'edit-mode':
@@ -2062,10 +2062,10 @@ function BudgetMenu({
 }
 
 function MonthSelector({ month, monthBounds, onPrevMonth, onNextMonth }) {
-  let prevEnabled = month > monthBounds.start;
-  let nextEnabled = month < monthUtils.subMonths(monthBounds.end, 1);
+  const prevEnabled = month > monthBounds.start;
+  const nextEnabled = month < monthUtils.subMonths(monthBounds.end, 1);
 
-  let arrowButtonStyle = {
+  const arrowButtonStyle = {
     padding: 10,
     margin: 2,
   };
diff --git a/packages/desktop-client/src/components/budget/MonthCountSelector.tsx b/packages/desktop-client/src/components/budget/MonthCountSelector.tsx
index 8a325e18f..c3509bc20 100644
--- a/packages/desktop-client/src/components/budget/MonthCountSelector.tsx
+++ b/packages/desktop-client/src/components/budget/MonthCountSelector.tsx
@@ -29,7 +29,7 @@ export function MonthCountSelector({
   maxMonths,
   onChange,
 }: MonthCountSelectorProps) {
-  let { displayMax } = useBudgetMonthCount();
+  const { displayMax } = useBudgetMonthCount();
 
   // It doesn't make sense to show anything if we can only fit one
   // month
@@ -37,7 +37,7 @@ export function MonthCountSelector({
     return null;
   }
 
-  let calendars = [];
+  const calendars = [];
   for (let i = 1; i <= displayMax; i++) {
     calendars.push(
       <Calendar
diff --git a/packages/desktop-client/src/components/budget/MonthPicker.tsx b/packages/desktop-client/src/components/budget/MonthPicker.tsx
index 7ee9c2206..b80e8e740 100644
--- a/packages/desktop-client/src/components/budget/MonthPicker.tsx
+++ b/packages/desktop-client/src/components/budget/MonthPicker.tsx
@@ -57,7 +57,7 @@ export const MonthPicker = ({
     );
   });
 
-  let yearHeadersShown = [];
+  const yearHeadersShown = [];
 
   return (
     <View
diff --git a/packages/desktop-client/src/components/budget/MonthsContext.tsx b/packages/desktop-client/src/components/budget/MonthsContext.tsx
index 3292929df..bca1acfe3 100644
--- a/packages/desktop-client/src/components/budget/MonthsContext.tsx
+++ b/packages/desktop-client/src/components/budget/MonthsContext.tsx
@@ -23,7 +23,7 @@ type MonthsContextProps = {
   type: string;
 };
 
-export let MonthsContext = createContext<MonthsContextProps>(null);
+export const MonthsContext = createContext<MonthsContextProps>(null);
 
 type MonthsProviderProps = {
   startMonth: string | undefined;
@@ -40,9 +40,9 @@ export function MonthsProvider({
   type,
   children,
 }: MonthsProviderProps) {
-  let endMonth = monthUtils.addMonths(startMonth, numMonths - 1);
-  let bounds = getValidMonthBounds(monthBounds, startMonth, endMonth);
-  let months = monthUtils.rangeInclusive(bounds.start, bounds.end);
+  const endMonth = monthUtils.addMonths(startMonth, numMonths - 1);
+  const bounds = getValidMonthBounds(monthBounds, startMonth, endMonth);
+  const months = monthUtils.rangeInclusive(bounds.start, bounds.end);
 
   return (
     <MonthsContext.Provider value={{ months, type }}>
diff --git a/packages/desktop-client/src/components/budget/RenderMonths.tsx b/packages/desktop-client/src/components/budget/RenderMonths.tsx
index 362ebafce..649734d97 100644
--- a/packages/desktop-client/src/components/budget/RenderMonths.tsx
+++ b/packages/desktop-client/src/components/budget/RenderMonths.tsx
@@ -25,10 +25,10 @@ function RenderMonths({
   args,
   style,
 }: RenderMonthsProps) {
-  let { months } = useContext(MonthsContext);
+  const { months } = useContext(MonthsContext);
 
   return months.map((month, index) => {
-    let editing = editingIndex === index;
+    const editing = editingIndex === index;
 
     return (
       <NamespaceContext.Provider
diff --git a/packages/desktop-client/src/components/budget/index.tsx b/packages/desktop-client/src/components/budget/index.tsx
index d72b15de9..db90edc08 100644
--- a/packages/desktop-client/src/components/budget/index.tsx
+++ b/packages/desktop-client/src/components/budget/index.tsx
@@ -122,17 +122,17 @@ function Budget(props: BudgetProps) {
   );
 
   async function loadCategories() {
-    let result = await props.getCategories();
+    const result = await props.getCategories();
     setCategoryGroups(result.grouped);
   }
 
   useEffect(() => {
-    let { titlebar, budgetType } = props;
+    const { titlebar, budgetType } = props;
 
     async function run() {
       loadCategories();
 
-      let { start, end } = await send('get-budget-bounds');
+      const { start, end } = await send('get-budget-bounds');
       setBounds({ start, end });
 
       await prewarmAllMonths(
@@ -147,7 +147,7 @@ function Budget(props: BudgetProps) {
 
     run();
 
-    let unlistens = [
+    const unlistens = [
       listen('sync-event', ({ type, tables }) => {
         if (
           type === 'success' &&
@@ -255,7 +255,7 @@ function Budget(props: BudgetProps) {
   };
 
   const onSaveCategory = async category => {
-    let exists =
+    const exists =
       (await props.getCategories()).grouped
         .filter(g => g.id === category.cat_group)[0]
         .categories.filter(
@@ -270,7 +270,7 @@ function Budget(props: BudgetProps) {
     }
 
     if (category.id === 'new') {
-      let id = await props.createCategory(
+      const id = await props.createCategory(
         category.name,
         category.cat_group,
         category.is_income,
@@ -313,7 +313,7 @@ function Budget(props: BudgetProps) {
 
   const onSaveGroup = async group => {
     if (group.id === 'new') {
-      let id = await props.createGroup(group.name);
+      const id = await props.createGroup(group.name);
       setIsAddingGroup(false);
       setCategoryGroups(state =>
         addGroup(state, {
@@ -330,10 +330,10 @@ function Budget(props: BudgetProps) {
   };
 
   const onDeleteGroup = async id => {
-    let group = categoryGroups.find(g => g.id === id);
+    const group = categoryGroups.find(g => g.id === id);
 
     let mustTransfer = false;
-    for (let category of group.categories) {
+    for (const category of group.categories) {
       if (await send('must-category-transfer', { id: category.id })) {
         mustTransfer = true;
         break;
@@ -377,9 +377,9 @@ function Budget(props: BudgetProps) {
   };
 
   const onReorderCategory = async sortInfo => {
-    let cats = await props.getCategories();
-    let moveCandidate = cats.list.filter(c => c.id === sortInfo.id)[0];
-    let exists =
+    const cats = await props.getCategories();
+    const moveCandidate = cats.list.filter(c => c.id === sortInfo.id)[0];
+    const exists =
       cats.grouped
         .filter(g => g.id === sortInfo.groupId)[0]
         .categories.filter(
@@ -406,7 +406,7 @@ function Budget(props: BudgetProps) {
   };
 
   const onToggleCollapse = () => {
-    let collapsed = !summaryCollapsed;
+    const collapsed = !summaryCollapsed;
     setSummaryCollapsed(collapsed);
     props.savePrefs({ 'budget.summaryCollapsed': collapsed });
   };
@@ -427,14 +427,14 @@ function Budget(props: BudgetProps) {
     }
   };
 
-  let {
-    maxMonths,
+  const {
+    maxMonths: originalMaxMonths,
     budgetType: type,
     reportComponents,
     rolloverComponents,
   } = props;
 
-  maxMonths = maxMonths || 1;
+  const maxMonths = originalMaxMonths || 1;
 
   if (!initialized || !categoryGroups) {
     return null;
@@ -532,27 +532,29 @@ const RolloverBudgetSummary = memo<{ month: string }>(props => {
 });
 
 export default function BudgetWrapper(props) {
-  let startMonth = useSelector(state => state.prefs.local['budget.startMonth']);
-  let collapsedPrefs = useSelector(
+  const startMonth = useSelector(
+    state => state.prefs.local['budget.startMonth'],
+  );
+  const collapsedPrefs = useSelector(
     state => state.prefs.local['budget.collapsed'],
   );
-  let summaryCollapsed = useSelector(
+  const summaryCollapsed = useSelector(
     state => state.prefs.local['budget.summaryCollapsed'],
   );
-  let budgetType = useSelector(
+  const budgetType = useSelector(
     state => state.prefs.local.budgetType || 'rollover',
   );
-  let maxMonths = useSelector(state => state.prefs.global.maxMonths);
-  let { grouped: categoryGroups } = useCategories();
+  const maxMonths = useSelector(state => state.prefs.global.maxMonths);
+  const { grouped: categoryGroups } = useCategories();
 
-  let actions = useActions();
-  let spreadsheet = useSpreadsheet();
-  let titlebar = useContext(TitlebarContext);
-  let location = useLocation();
-  let match = useMatch(location.pathname);
-  let navigate = useNavigate();
+  const actions = useActions();
+  const spreadsheet = useSpreadsheet();
+  const titlebar = useContext(TitlebarContext);
+  const location = useLocation();
+  const match = useMatch(location.pathname);
+  const navigate = useNavigate();
 
-  let reportComponents = useMemo<ReportComponents>(
+  const reportComponents = useMemo<ReportComponents>(
     () => ({
       SummaryComponent: report.BudgetSummary,
       ExpenseCategoryComponent: report.ExpenseCategoryMonth,
@@ -565,7 +567,7 @@ export default function BudgetWrapper(props) {
     [report],
   );
 
-  let rolloverComponents = useMemo<RolloverComponents>(
+  const rolloverComponents = useMemo<RolloverComponents>(
     () => ({
       SummaryComponent: RolloverBudgetSummary,
       ExpenseCategoryComponent: rollover.ExpenseCategoryMonth,
diff --git a/packages/desktop-client/src/components/budget/report/BalanceTooltip.tsx b/packages/desktop-client/src/components/budget/report/BalanceTooltip.tsx
index 4d34915a5..c1c297518 100644
--- a/packages/desktop-client/src/components/budget/report/BalanceTooltip.tsx
+++ b/packages/desktop-client/src/components/budget/report/BalanceTooltip.tsx
@@ -22,9 +22,9 @@ export default function BalanceTooltip({
   onClose,
   ...tooltipProps
 }: BalanceTooltipProps) {
-  let carryover = useSheetValue(reportBudget.catCarryover(categoryId));
+  const carryover = useSheetValue(reportBudget.catCarryover(categoryId));
 
-  let _onClose = () => {
+  const _onClose = () => {
     tooltip.close();
     onClose?.();
   };
diff --git a/packages/desktop-client/src/components/budget/report/ReportComponents.tsx b/packages/desktop-client/src/components/budget/report/ReportComponents.tsx
index 1d3d03bb8..ed38d3bab 100644
--- a/packages/desktop-client/src/components/budget/report/ReportComponents.tsx
+++ b/packages/desktop-client/src/components/budget/report/ReportComponents.tsx
@@ -20,7 +20,7 @@ import { makeAmountGrey } from '../util';
 
 import BalanceTooltip from './BalanceTooltip';
 
-let headerLabelStyle: CSSProperties = {
+const headerLabelStyle: CSSProperties = {
   flex: 1,
   padding: '0 5px',
   textAlign: 'right',
@@ -91,7 +91,7 @@ type GroupMonthProps = {
   group: { id: string; is_income: boolean };
 };
 export const GroupMonth = memo(function GroupMonth({ group }: GroupMonthProps) {
-  let { id } = group;
+  const { id } = group;
 
   return (
     <View style={{ flex: 1, flexDirection: 'row' }}>
@@ -156,7 +156,7 @@ export const CategoryMonth = memo(function CategoryMonth({
   onBudgetAction,
   onShowActivity,
 }: CategoryMonthProps) {
-  let balanceTooltip = useTooltip();
+  const balanceTooltip = useTooltip();
   const [menuOpen, setMenuOpen] = useState(false);
   const [hover, setHover] = useState(false);
   const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
diff --git a/packages/desktop-client/src/components/budget/report/ReportContext.tsx b/packages/desktop-client/src/components/budget/report/ReportContext.tsx
index 3f746cfd5..e38b4da86 100644
--- a/packages/desktop-client/src/components/budget/report/ReportContext.tsx
+++ b/packages/desktop-client/src/components/budget/report/ReportContext.tsx
@@ -2,7 +2,7 @@ import React, { type ReactNode, createContext, useContext } from 'react';
 
 import * as monthUtils from 'loot-core/src/shared/months';
 
-let Context = createContext(null);
+const Context = createContext(null);
 
 type ReportProviderProps = {
   summaryCollapsed: boolean;
@@ -16,7 +16,7 @@ export function ReportProvider({
   onToggleSummaryCollapse,
   children,
 }: ReportProviderProps) {
-  let currentMonth = monthUtils.currentMonth();
+  const currentMonth = monthUtils.currentMonth();
 
   return (
     <Context.Provider
diff --git a/packages/desktop-client/src/components/budget/report/budgetsummary/BudgetSummary.tsx b/packages/desktop-client/src/components/budget/report/budgetsummary/BudgetSummary.tsx
index d1f726a7e..58e18d32a 100644
--- a/packages/desktop-client/src/components/budget/report/budgetsummary/BudgetSummary.tsx
+++ b/packages/desktop-client/src/components/budget/report/budgetsummary/BudgetSummary.tsx
@@ -26,7 +26,7 @@ type BudgetSummaryProps = {
   month?: string;
 };
 export default function BudgetSummary({ month }: BudgetSummaryProps) {
-  let {
+  const {
     currentMonth,
     summaryCollapsed: collapsed,
     onBudgetAction,
@@ -35,7 +35,7 @@ export default function BudgetSummary({ month }: BudgetSummaryProps) {
 
   const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
 
-  let [menuOpen, setMenuOpen] = useState(false);
+  const [menuOpen, setMenuOpen] = useState(false);
   function onMenuOpen() {
     setMenuOpen(true);
   }
@@ -44,7 +44,7 @@ export default function BudgetSummary({ month }: BudgetSummaryProps) {
     setMenuOpen(false);
   }
 
-  let ExpandOrCollapseIcon = collapsed ? ArrowButtonDown1 : ArrowButtonUp1;
+  const ExpandOrCollapseIcon = collapsed ? ArrowButtonDown1 : ArrowButtonUp1;
 
   return (
     <View
diff --git a/packages/desktop-client/src/components/budget/report/budgetsummary/ExpenseProgress.tsx b/packages/desktop-client/src/components/budget/report/budgetsummary/ExpenseProgress.tsx
index 5f5120cde..4613c9576 100644
--- a/packages/desktop-client/src/components/budget/report/budgetsummary/ExpenseProgress.tsx
+++ b/packages/desktop-client/src/components/budget/report/budgetsummary/ExpenseProgress.tsx
@@ -13,7 +13,7 @@ type ExpenseProgressProps = {
 };
 export function ExpenseProgress({ current, target }: ExpenseProgressProps) {
   let totalSpent = useSheetValue(current) || 0;
-  let totalBudgeted = useSheetValue(target) || 0;
+  const totalBudgeted = useSheetValue(target) || 0;
 
   // Reverse total spent, and also set a bottom boundary of 0 (in case
   // income goes into an expense category and it's "positive", don't
diff --git a/packages/desktop-client/src/components/budget/report/budgetsummary/IncomeProgress.tsx b/packages/desktop-client/src/components/budget/report/budgetsummary/IncomeProgress.tsx
index 7a13d213d..33f731711 100644
--- a/packages/desktop-client/src/components/budget/report/budgetsummary/IncomeProgress.tsx
+++ b/packages/desktop-client/src/components/budget/report/budgetsummary/IncomeProgress.tsx
@@ -16,7 +16,7 @@ export default function IncomeProgress({
   target,
 }: IncomeProgressProps) {
   let totalIncome = useSheetValue(current) || 0;
-  let totalBudgeted = useSheetValue(target) || 0;
+  const totalBudgeted = useSheetValue(target) || 0;
 
   let over = false;
 
@@ -25,7 +25,7 @@ export default function IncomeProgress({
     totalIncome = -totalIncome;
   }
 
-  let frac = fraction(totalIncome, totalBudgeted);
+  const frac = fraction(totalIncome, totalBudgeted);
 
   return (
     <PieProgress
diff --git a/packages/desktop-client/src/components/budget/report/budgetsummary/PieProgress.tsx b/packages/desktop-client/src/components/budget/report/budgetsummary/PieProgress.tsx
index 32cba3df5..7f655168f 100644
--- a/packages/desktop-client/src/components/budget/report/budgetsummary/PieProgress.tsx
+++ b/packages/desktop-client/src/components/budget/report/budgetsummary/PieProgress.tsx
@@ -12,10 +12,10 @@ export default function PieProgress({
   color,
   backgroundColor,
 }: PieProgressProps) {
-  let radius = 4;
-  let circum = 2 * Math.PI * radius;
-  let dash = progress * circum;
-  let gap = circum;
+  const radius = 4;
+  const circum = 2 * Math.PI * radius;
+  const dash = progress * circum;
+  const gap = circum;
 
   return (
     <svg viewBox="0 0 20 20" style={style}>
diff --git a/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx b/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx
index 8c8768e3e..80fbf1b74 100644
--- a/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx
+++ b/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx
@@ -20,11 +20,11 @@ type SavedProps = {
   style?: CSSProperties;
 };
 export default function Saved({ projected, style }: SavedProps) {
-  let budgetedSaved = useSheetValue(reportBudget.totalBudgetedSaved) || 0;
-  let totalSaved = useSheetValue(reportBudget.totalSaved) || 0;
-  let format = useFormat();
-  let saved = projected ? budgetedSaved : totalSaved;
-  let isNegative = saved < 0;
+  const budgetedSaved = useSheetValue(reportBudget.totalBudgetedSaved) || 0;
+  const totalSaved = useSheetValue(reportBudget.totalSaved) || 0;
+  const format = useFormat();
+  const saved = projected ? budgetedSaved : totalSaved;
+  const isNegative = saved < 0;
 
   return (
     <View style={{ alignItems: 'center', fontSize: 14, ...style }}>
@@ -39,7 +39,7 @@ export default function Saved({ projected, style }: SavedProps) {
       <HoverTarget
         renderContent={() => {
           if (!projected) {
-            let diff = totalSaved - budgetedSaved;
+            const diff = totalSaved - budgetedSaved;
             return (
               <Tooltip
                 position="bottom-center"
diff --git a/packages/desktop-client/src/components/budget/rollover/BalanceTooltip.tsx b/packages/desktop-client/src/components/budget/rollover/BalanceTooltip.tsx
index cf959c9a9..6df17d977 100644
--- a/packages/desktop-client/src/components/budget/rollover/BalanceTooltip.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/BalanceTooltip.tsx
@@ -24,11 +24,11 @@ export default function BalanceTooltip({
   onClose,
   ...tooltipProps
 }: BalanceTooltipProps) {
-  let carryover = useSheetValue(rolloverBudget.catCarryover(categoryId));
-  let balance = useSheetValue(rolloverBudget.catBalance(categoryId));
-  let [menu, setMenu] = useState('menu');
+  const carryover = useSheetValue(rolloverBudget.catCarryover(categoryId));
+  const balance = useSheetValue(rolloverBudget.catBalance(categoryId));
+  const [menu, setMenu] = useState('menu');
 
-  let _onClose = () => {
+  const _onClose = () => {
     tooltip.close();
     onClose?.();
   };
diff --git a/packages/desktop-client/src/components/budget/rollover/CoverTooltip.tsx b/packages/desktop-client/src/components/budget/rollover/CoverTooltip.tsx
index 9e24fcaf6..2605e5df2 100644
--- a/packages/desktop-client/src/components/budget/rollover/CoverTooltip.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/CoverTooltip.tsx
@@ -22,7 +22,7 @@ export default function CoverTooltip({
   categoryGroups = addToBeBudgetedGroup(
     categoryGroups.filter(g => !g.is_income),
   );
-  let [category, setCategory] = useState(null);
+  const [category, setCategory] = useState(null);
 
   function submit() {
     if (category) {
diff --git a/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx b/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx
index 747770a7d..e34a1322d 100644
--- a/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx
@@ -20,7 +20,7 @@ import { makeAmountGrey } from '../util';
 
 import BalanceTooltip from './BalanceTooltip';
 
-let headerLabelStyle: CSSProperties = {
+const headerLabelStyle: CSSProperties = {
   flex: 1,
   padding: '0 5px',
   textAlign: 'right',
@@ -89,7 +89,7 @@ type ExpenseGroupMonthProps = {
 export const ExpenseGroupMonth = memo(function ExpenseGroupMonth({
   group,
 }: ExpenseGroupMonthProps) {
-  let { id } = group;
+  const { id } = group;
 
   return (
     <View style={{ flex: 1, flexDirection: 'row' }}>
@@ -152,7 +152,7 @@ export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({
   onBudgetAction,
   onShowActivity,
 }: ExpenseCategoryMonthProps) {
-  let balanceTooltip = useTooltip();
+  const balanceTooltip = useTooltip();
   const [menuOpen, setMenuOpen] = useState(false);
   const [hover, setHover] = useState(false);
   const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
diff --git a/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx b/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx
index 7006ae78e..3d825c834 100644
--- a/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx
@@ -2,7 +2,7 @@ import React, { type ReactNode, createContext, useContext } from 'react';
 
 import * as monthUtils from 'loot-core/src/shared/months';
 
-let Context = createContext(null);
+const Context = createContext(null);
 
 type RolloverContextProps = {
   categoryGroups: unknown[];
@@ -18,7 +18,7 @@ export function RolloverContext({
   onToggleSummaryCollapse,
   children,
 }: RolloverContextProps) {
-  let currentMonth = monthUtils.currentMonth();
+  const currentMonth = monthUtils.currentMonth();
 
   return (
     <Context.Provider
diff --git a/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx b/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx
index 4aa10527c..5e7c38216 100644
--- a/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx
@@ -34,8 +34,8 @@ export default function TransferTooltip({
   position = 'bottom-right',
   ...props
 }: TransferTooltipProps) {
-  let spreadsheet = useSpreadsheet();
-  let sheetName = useContext(NamespaceContext);
+  const spreadsheet = useSpreadsheet();
+  const sheetName = useContext(NamespaceContext);
   let { grouped: categoryGroups } = useCategories();
 
   categoryGroups = categoryGroups.filter(g => !g.is_income);
@@ -43,8 +43,8 @@ export default function TransferTooltip({
     categoryGroups = addToBeBudgetedGroup(categoryGroups);
   }
 
-  let [amount, setAmount] = useState(null);
-  let [category, setCategory] = useState(null);
+  const [amount, setAmount] = useState(null);
+  const [category, setCategory] = useState(null);
 
   useEffect(() => {
     (async () => {
@@ -58,7 +58,7 @@ export default function TransferTooltip({
   }, []);
 
   function submit() {
-    let parsedAmount = evalArithmetic(amount, null);
+    const parsedAmount = evalArithmetic(amount, null);
     if (parsedAmount && category) {
       onSubmit(amountToInteger(parsedAmount), category);
       onClose();
diff --git a/packages/desktop-client/src/components/budget/rollover/budgetsummary/BudgetSummary.tsx b/packages/desktop-client/src/components/budget/rollover/budgetsummary/BudgetSummary.tsx
index 5cbf8f573..0a5c73b9c 100644
--- a/packages/desktop-client/src/components/budget/rollover/budgetsummary/BudgetSummary.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/budgetsummary/BudgetSummary.tsx
@@ -27,14 +27,14 @@ export default function BudgetSummary({
   month,
   isGoalTemplatesEnabled,
 }: BudgetSummaryProps) {
-  let {
+  const {
     currentMonth,
     summaryCollapsed: collapsed,
     onBudgetAction,
     onToggleSummaryCollapse,
   } = useRollover();
 
-  let [menuOpen, setMenuOpen] = useState(false);
+  const [menuOpen, setMenuOpen] = useState(false);
   function onMenuOpen(e) {
     setMenuOpen(true);
   }
@@ -43,9 +43,9 @@ export default function BudgetSummary({
     setMenuOpen(false);
   }
 
-  let prevMonthName = monthUtils.format(monthUtils.prevMonth(month), 'MMM');
+  const prevMonthName = monthUtils.format(monthUtils.prevMonth(month), 'MMM');
 
-  let ExpandOrCollapseIcon = collapsed ? ArrowButtonDown1 : ArrowButtonUp1;
+  const ExpandOrCollapseIcon = collapsed ? ArrowButtonDown1 : ArrowButtonUp1;
 
   return (
     <View
diff --git a/packages/desktop-client/src/components/budget/rollover/budgetsummary/ToBudget.tsx b/packages/desktop-client/src/components/budget/rollover/budgetsummary/ToBudget.tsx
index e024e322d..184456c76 100644
--- a/packages/desktop-client/src/components/budget/rollover/budgetsummary/ToBudget.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/budgetsummary/ToBudget.tsx
@@ -43,16 +43,16 @@ export default function ToBudget({
   holdTooltipProps,
   transferTooltipProps,
 }: ToBudgetProps) {
-  let [menuOpen, setMenuOpen] = useState(null);
-  let sheetName = useSheetName(rolloverBudget.toBudget);
-  let sheetValue = useSheetValue({
+  const [menuOpen, setMenuOpen] = useState(null);
+  const sheetName = useSheetName(rolloverBudget.toBudget);
+  const sheetValue = useSheetValue({
     name: rolloverBudget.toBudget,
     value: 0,
   });
-  let format = useFormat();
-  let availableValue = parseInt(sheetValue);
-  let num = isNaN(availableValue) ? 0 : availableValue;
-  let isNegative = num < 0;
+  const format = useFormat();
+  const availableValue = parseInt(sheetValue);
+  const num = isNaN(availableValue) ? 0 : availableValue;
+  const isNegative = num < 0;
 
   return (
     <View style={{ alignItems: 'center', ...style }}>
diff --git a/packages/desktop-client/src/components/budget/rollover/budgetsummary/TotalsList.tsx b/packages/desktop-client/src/components/budget/rollover/budgetsummary/TotalsList.tsx
index 0805b8bac..20a5fd4b9 100644
--- a/packages/desktop-client/src/components/budget/rollover/budgetsummary/TotalsList.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/budgetsummary/TotalsList.tsx
@@ -75,7 +75,7 @@ export default function TotalsList({ prevMonthName, style }: TotalsListProps) {
           binding={rolloverBudget.lastMonthOverspent}
           type="financial"
           formatter={value => {
-            let v = format(value, 'financial');
+            const v = format(value, 'financial');
             return value > 0 ? '+' + v : value === 0 ? '-' + v : v;
           }}
           style={{ fontWeight: 600, ...styles.tnum }}
@@ -85,7 +85,7 @@ export default function TotalsList({ prevMonthName, style }: TotalsListProps) {
           binding={rolloverBudget.totalBudgeted}
           type="financial"
           formatter={value => {
-            let v = format(value, 'financial');
+            const v = format(value, 'financial');
             return value > 0 ? '+' + v : value === 0 ? '-' + v : v;
           }}
           style={{ fontWeight: 600, ...styles.tnum }}
@@ -95,8 +95,8 @@ export default function TotalsList({ prevMonthName, style }: TotalsListProps) {
           binding={rolloverBudget.forNextMonth}
           type="financial"
           formatter={value => {
-            let n = parseInt(value) || 0;
-            let v = format(Math.abs(n), 'financial');
+            const n = parseInt(value) || 0;
+            const v = format(Math.abs(n), 'financial');
             return n >= 0 ? '-' + v : '+' + v;
           }}
           style={{ fontWeight: 600, ...styles.tnum }}
diff --git a/packages/desktop-client/src/components/budget/util.ts b/packages/desktop-client/src/components/budget/util.ts
index 6e9f7dd14..b1e7d7d5c 100644
--- a/packages/desktop-client/src/components/budget/util.ts
+++ b/packages/desktop-client/src/components/budget/util.ts
@@ -85,13 +85,13 @@ export function findSortDown(
   if (pos === 'top') {
     return { targetId };
   } else {
-    let idx = arr.findIndex(item => item.id === targetId);
+    const idx = arr.findIndex(item => item.id === targetId);
 
     if (idx === -1) {
       throw new Error('findSort: item not found: ' + targetId);
     }
 
-    let newIdx = idx + 1;
+    const newIdx = idx + 1;
     if (newIdx < arr.length - 1) {
       return { targetId: arr[newIdx].id };
     } else {
@@ -109,13 +109,13 @@ export function findSortUp(
   if (pos === 'bottom') {
     return { targetId };
   } else {
-    let idx = arr.findIndex(item => item.id === targetId);
+    const idx = arr.findIndex(item => item.id === targetId);
 
     if (idx === -1) {
       throw new Error('findSort: item not found: ' + targetId);
     }
 
-    let newIdx = idx - 1;
+    const newIdx = idx - 1;
     if (newIdx >= 0) {
       return { targetId: arr[newIdx].id };
     } else {
@@ -134,12 +134,12 @@ export async function prewarmMonth(
   spreadsheet: ReturnType<typeof useSpreadsheet>,
   month: string,
 ) {
-  let method: keyof Handlers =
+  const method: keyof Handlers =
     budgetType === 'report' ? 'report-budget-month' : 'rollover-budget-month';
 
-  let values = await send(method, { month });
+  const values = await send(method, { month });
 
-  for (let value of values) {
+  for (const value of values) {
     spreadsheet.prewarmCache(value.name, value);
   }
 }
@@ -150,14 +150,14 @@ export async function prewarmAllMonths(
   bounds: { start: string; end: string },
   startMonth: string,
 ) {
-  let numMonths = 3;
+  const numMonths = 3;
 
   bounds = getValidMonthBounds(
     bounds,
     monthUtils.subMonths(startMonth, 1),
     monthUtils.addMonths(startMonth, numMonths + 1),
   );
-  let months = monthUtils.rangeInclusive(bounds.start, bounds.end);
+  const months = monthUtils.rangeInclusive(bounds.start, bounds.end);
 
   await Promise.all(
     months.map(month => prewarmMonth(budgetType, spreadsheet, month)),
diff --git a/packages/desktop-client/src/components/common/AnchorLink.tsx b/packages/desktop-client/src/components/common/AnchorLink.tsx
index c1ea47493..2cc6ba3fd 100644
--- a/packages/desktop-client/src/components/common/AnchorLink.tsx
+++ b/packages/desktop-client/src/components/common/AnchorLink.tsx
@@ -18,7 +18,7 @@ export default function AnchorLink({
   activeStyle,
   children,
 }: AnchorLinkProps) {
-  let match = useMatch({ path: to });
+  const match = useMatch({ path: to });
 
   return (
     <NavLink
diff --git a/packages/desktop-client/src/components/common/Button.tsx b/packages/desktop-client/src/components/common/Button.tsx
index a421059ae..f99e0adec 100644
--- a/packages/desktop-client/src/components/common/Button.tsx
+++ b/packages/desktop-client/src/components/common/Button.tsx
@@ -149,7 +149,7 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
     },
     ref,
   ) => {
-    let typeWithDisabled = disabled ? type + 'Disabled' : type;
+    const typeWithDisabled = disabled ? type + 'Disabled' : type;
 
     hoveredStyle = {
       ...(type !== 'bare' && styles.shadow),
@@ -163,8 +163,8 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
       ...activeStyle,
     };
 
-    let Component = as;
-    let buttonStyle = {
+    const Component = as;
+    const buttonStyle = {
       alignItems: 'center',
       justifyContent: 'center',
       flexShrink: 0,
@@ -211,7 +211,7 @@ export const ButtonWithLoading = forwardRef<
   HTMLButtonElement,
   ButtonWithLoadingProps
 >((props, ref) => {
-  let { loading, children, ...buttonProps } = props;
+  const { loading, children, ...buttonProps } = props;
   return (
     <Button
       {...buttonProps}
diff --git a/packages/desktop-client/src/components/common/ExternalLink.tsx b/packages/desktop-client/src/components/common/ExternalLink.tsx
index 6c37ea582..f31d240c9 100644
--- a/packages/desktop-client/src/components/common/ExternalLink.tsx
+++ b/packages/desktop-client/src/components/common/ExternalLink.tsx
@@ -2,7 +2,7 @@ import React, { type ReactNode, forwardRef } from 'react';
 
 import { theme } from '../../style';
 
-let externalLinkColors = {
+const externalLinkColors = {
   purple: theme.pageTextPositive,
   blue: theme.pageTextLink,
   muted: 'inherit',
diff --git a/packages/desktop-client/src/components/common/HoverTarget.tsx b/packages/desktop-client/src/components/common/HoverTarget.tsx
index bbaa27b87..097ad9c01 100644
--- a/packages/desktop-client/src/components/common/HoverTarget.tsx
+++ b/packages/desktop-client/src/components/common/HoverTarget.tsx
@@ -19,7 +19,7 @@ export default function HoverTarget({
   renderContent,
   disabled,
 }: HoverTargetProps) {
-  let [hovered, setHovered] = useState(false);
+  const [hovered, setHovered] = useState(false);
 
   const onPointerEnter = useCallback(() => {
     if (!disabled) {
diff --git a/packages/desktop-client/src/components/common/InitialFocus.tsx b/packages/desktop-client/src/components/common/InitialFocus.tsx
index 7c6ad0a65..6f88cbb60 100644
--- a/packages/desktop-client/src/components/common/InitialFocus.tsx
+++ b/packages/desktop-client/src/components/common/InitialFocus.tsx
@@ -11,7 +11,7 @@ type InitialFocusProps = {
 };
 
 export default function InitialFocus({ children }: InitialFocusProps) {
-  let node = useRef(null);
+  const node = useRef(null);
 
   useEffect(() => {
     if (node.current && !global.IS_DESIGN_MODE) {
diff --git a/packages/desktop-client/src/components/common/Input.tsx b/packages/desktop-client/src/components/common/Input.tsx
index d52842514..6a4e6eaf9 100644
--- a/packages/desktop-client/src/components/common/Input.tsx
+++ b/packages/desktop-client/src/components/common/Input.tsx
@@ -37,7 +37,7 @@ export default function Input({
   focused,
   ...nativeProps
 }: InputProps) {
-  let ref = useRef();
+  const ref = useRef();
   useProperFocus(ref, focused);
 
   return (
diff --git a/packages/desktop-client/src/components/common/InputWithContent.tsx b/packages/desktop-client/src/components/common/InputWithContent.tsx
index 6321a7d85..24b357342 100644
--- a/packages/desktop-client/src/components/common/InputWithContent.tsx
+++ b/packages/desktop-client/src/components/common/InputWithContent.tsx
@@ -22,7 +22,7 @@ export default function InputWithContent({
   getStyle,
   ...props
 }: InputWithContentProps) {
-  let [focused, setFocused] = useState(props.focused);
+  const [focused, setFocused] = useState(props.focused);
 
   return (
     <View
diff --git a/packages/desktop-client/src/components/common/Menu.tsx b/packages/desktop-client/src/components/common/Menu.tsx
index be4382405..1d0258cd7 100644
--- a/packages/desktop-client/src/components/common/Menu.tsx
+++ b/packages/desktop-client/src/components/common/Menu.tsx
@@ -46,21 +46,21 @@ export default function Menu({
   items: allItems,
   onMenuSelect,
 }: MenuProps) {
-  let elRef = useRef(null);
-  let items = allItems.filter(x => x);
-  let [hoveredIndex, setHoveredIndex] = useState(null);
+  const elRef = useRef(null);
+  const items = allItems.filter(x => x);
+  const [hoveredIndex, setHoveredIndex] = useState(null);
 
   useEffect(() => {
     const el = elRef.current;
     el.focus();
 
-    let onKeyDown = e => {
-      let filteredItems = items.filter(
+    const onKeyDown = e => {
+      const filteredItems = items.filter(
         item => item && item !== Menu.line && item.type !== Menu.label,
       );
-      let currentIndex = filteredItems.indexOf(items[hoveredIndex]);
+      const currentIndex = filteredItems.indexOf(items[hoveredIndex]);
 
-      let transformIndex = idx => items.indexOf(filteredItems[idx]);
+      const transformIndex = idx => items.indexOf(filteredItems[idx]);
 
       switch (e.key) {
         case 'ArrowUp':
@@ -131,7 +131,7 @@ export default function Menu({
           );
         }
 
-        let lastItem = items[idx - 1];
+        const lastItem = items[idx - 1];
 
         return (
           <View
diff --git a/packages/desktop-client/src/components/common/Modal.tsx b/packages/desktop-client/src/components/common/Modal.tsx
index a03bdd004..3eac7bf30 100644
--- a/packages/desktop-client/src/components/common/Modal.tsx
+++ b/packages/desktop-client/src/components/common/Modal.tsx
@@ -64,7 +64,7 @@ const Modal = ({
     // This deactivates any key handlers in the "app" scope. Ideally
     // each modal would have a name so they could each have their own
     // key handlers, but we'll do that later
-    let prevScope = hotkeys.getScope();
+    const prevScope = hotkeys.getScope();
     hotkeys.setScope('modal');
     return () => hotkeys.setScope(prevScope);
   }, []);
@@ -243,9 +243,9 @@ const ModalContent = ({
   stackIndex,
   children,
 }: ModalContentProps) => {
-  let contentRef = useRef(null);
-  let mounted = useRef(false);
-  let rotateFactor = useRef(Math.random() * 10 - 5);
+  const contentRef = useRef(null);
+  const mounted = useRef(false);
+  const rotateFactor = useRef(Math.random() * 10 - 5);
 
   useLayoutEffect(() => {
     if (contentRef.current == null) {
@@ -319,11 +319,11 @@ export const ModalButtons = ({
   focusButton = false,
   children,
 }: ModalButtonsProps) => {
-  let containerRef = useRef(null);
+  const containerRef = useRef(null);
 
   useEffect(() => {
     if (focusButton && containerRef.current) {
-      let button = containerRef.current.querySelector(
+      const button = containerRef.current.querySelector(
         'button:not([data-hidden])',
       );
 
diff --git a/packages/desktop-client/src/components/common/Stack.tsx b/packages/desktop-client/src/components/common/Stack.tsx
index a59cf5a9f..1a3df4f0f 100644
--- a/packages/desktop-client/src/components/common/Stack.tsx
+++ b/packages/desktop-client/src/components/common/Stack.tsx
@@ -66,7 +66,7 @@ const Stack = forwardRef<HTMLDivElement, StackProps>(
         {...props}
       >
         {validChildren.map(({ key, child }, index) => {
-          let isLastChild = validChildren.length === index + 1;
+          const isLastChild = validChildren.length === index + 1;
 
           let marginProp;
           if (isHorizontal) {
diff --git a/packages/desktop-client/src/components/filters/FiltersMenu.js b/packages/desktop-client/src/components/filters/FiltersMenu.js
index 2c1b6d58e..16034382c 100644
--- a/packages/desktop-client/src/components/filters/FiltersMenu.js
+++ b/packages/desktop-client/src/components/filters/FiltersMenu.js
@@ -40,7 +40,7 @@ import CompactFiltersButton from './CompactFiltersButton';
 import FiltersButton from './FiltersButton';
 import { CondOpMenu } from './SavedFilters';
 
-let filterFields = [
+const filterFields = [
   'date',
   'account',
   'payee',
@@ -119,7 +119,7 @@ function OpButton({ op, selected, style, onClick }) {
 function updateFilterReducer(state, action) {
   switch (action.type) {
     case 'set-op': {
-      let type = FIELD_TYPES.get(state.field);
+      const type = FIELD_TYPES.get(state.field);
       let value = state.value;
       if (
         (type === 'id' || type === 'string') &&
@@ -135,7 +135,7 @@ function updateFilterReducer(state, action) {
       return { ...state, op: action.op, value };
     }
     case 'set-value': {
-      let { value } = makeValue(action.value, {
+      const { value } = makeValue(action.value, {
         type: FIELD_TYPES.get(state.field),
       });
       return { ...state, value };
@@ -153,9 +153,10 @@ function ConfigureField({
   dispatch,
   onApply,
 }) {
-  let [subfield, setSubfield] = useState(initialSubfield);
-  let inputRef = useRef();
-  let prevOp = useRef(null);
+  const [subfield, setSubfield] = useState(initialSubfield);
+  const inputRef = useRef();
+  const prevOp = useRef(null);
+
   useEffect(() => {
     if (prevOp.current !== op && inputRef.current) {
       inputRef.current.focus();
@@ -163,7 +164,7 @@ function ConfigureField({
     prevOp.current = op;
   }, [op]);
 
-  let type = FIELD_TYPES.get(field);
+  const type = FIELD_TYPES.get(field);
   let ops = TYPE_INFO[type].ops.filter(op => op !== 'isbetween');
 
   // Month and year fields are quite hacky right now! Figure out how
@@ -337,23 +338,23 @@ function ConfigureField({
 }
 
 export function FilterButton({ onApply, compact, hover }) {
-  let filters = useFilters();
+  const filters = useFilters();
 
-  let { dateFormat } = useSelector(state => {
+  const { dateFormat } = useSelector(state => {
     return {
       dateFormat: state.prefs.local.dateFormat || 'MM/dd/yyyy',
     };
   });
 
-  let [state, dispatch] = useReducer(
+  const [state, dispatch] = useReducer(
     (state, action) => {
       switch (action.type) {
         case 'select-field':
           return { ...state, fieldsOpen: true, condOpen: false };
         case 'configure': {
-          let { field } = deserializeField(action.field);
-          let type = FIELD_TYPES.get(field);
-          let ops = TYPE_INFO[type].ops;
+          const { field } = deserializeField(action.field);
+          const type = FIELD_TYPES.get(field);
+          const ops = TYPE_INFO[type].ops;
           return {
             ...state,
             fieldsOpen: false,
@@ -377,7 +378,7 @@ export function FilterButton({ onApply, compact, hover }) {
 
     if (cond.type === 'date' && cond.options) {
       if (cond.options.month) {
-        let date = parseDate(
+        const date = parseDate(
           cond.value,
           getMonthYearFormat(dateFormat),
           new Date(),
@@ -389,7 +390,7 @@ export function FilterButton({ onApply, compact, hover }) {
           return;
         }
       } else if (cond.options.year) {
-        let date = parseDate(cond.value, 'yyyy', new Date());
+        const date = parseDate(cond.value, 'yyyy', new Date());
         if (isDateValid(date)) {
           cond.value = formatDate(date, 'yyyy');
         } else {
@@ -399,17 +400,17 @@ export function FilterButton({ onApply, compact, hover }) {
       }
     }
 
-    let { error } =
+    const { error } =
       cond.field !== 'saved' &&
       (await send('rule-validate', {
         conditions: [cond],
         actions: [],
       }));
 
-    let saved = filters.find(f => cond.value === f.id);
+    const saved = filters.find(f => cond.value === f.id);
 
     if (error && error.conditionErrors.length > 0) {
-      let field = titleFirst(mapField(cond.field));
+      const field = titleFirst(mapField(cond.field));
       alert(field + ': ' + getFieldError(error.conditionErrors[0]));
     } else {
       onApply(saved ? saved : cond);
@@ -477,7 +478,7 @@ export function FilterButton({ onApply, compact, hover }) {
 }
 
 function FilterEditor({ field, op, value, options, onSave, onClose }) {
-  let [state, dispatch] = useReducer(
+  const [state, dispatch] = useReducer(
     (state, action) => {
       switch (action.type) {
         case 'close':
@@ -518,9 +519,10 @@ function FilterExpression({
   onChange,
   onDelete,
 }) {
-  let [editing, setEditing] = useState(false);
+  const [editing, setEditing] = useState(false);
+
+  const field = subfieldFromFilter({ field: originalField, value });
 
-  let field = subfieldFromFilter({ field: originalField, value });
   return (
     <View
       style={{
diff --git a/packages/desktop-client/src/components/filters/SavedFilters.js b/packages/desktop-client/src/components/filters/SavedFilters.js
index 31f88898f..fce9af440 100644
--- a/packages/desktop-client/src/components/filters/SavedFilters.js
+++ b/packages/desktop-client/src/components/filters/SavedFilters.js
@@ -67,7 +67,7 @@ function NameFilter({
   onAddUpdate,
   err,
 }) {
-  let inputRef = useRef();
+  const inputRef = useRef();
 
   useEffect(() => {
     if (inputRef.current) {
@@ -130,13 +130,13 @@ function SavedFilterMenuButton({
   onReloadSavedFilter,
   filtersList,
 }) {
-  let [nameOpen, setNameOpen] = useState(false);
-  let [adding, setAdding] = useState(false);
-  let [menuOpen, setMenuOpen] = useState(false);
-  let [err, setErr] = useState(null);
-  let [menuItem, setMenuItem] = useState(null);
-  let [name, setName] = useState(filterId.name);
-  let id = filterId.id;
+  const [nameOpen, setNameOpen] = useState(false);
+  const [adding, setAdding] = useState(false);
+  const [menuOpen, setMenuOpen] = useState(false);
+  const [err, setErr] = useState(null);
+  const [menuItem, setMenuItem] = useState(null);
+  const [name, setName] = useState(filterId.name);
+  const id = filterId.id;
   let res;
   let savedFilter;
 
diff --git a/packages/desktop-client/src/components/manager/BudgetList.js b/packages/desktop-client/src/components/manager/BudgetList.js
index 0f57c29f9..0d702504f 100644
--- a/packages/desktop-client/src/components/manager/BudgetList.js
+++ b/packages/desktop-client/src/components/manager/BudgetList.js
@@ -51,13 +51,13 @@ function FileMenu({ onDelete, onClose }) {
     }
   }
 
-  let items = [{ name: 'delete', text: 'Delete' }];
+  const items = [{ name: 'delete', text: 'Delete' }];
 
   return <Menu onMenuSelect={onMenuSelect} items={items} />;
 }
 
 function DetailButton({ state, onDelete }) {
-  let [menuOpen, setMenuOpen] = useState(false);
+  const [menuOpen, setMenuOpen] = useState(false);
 
   return (
     <View>
@@ -137,7 +137,7 @@ function FileState({ file }) {
 }
 
 function File({ file, onSelect, onDelete }) {
-  let selecting = useRef(false);
+  const selecting = useRef(false);
 
   async function _onSelect(file) {
     // Never allow selecting the file while uploading/downloading, and
@@ -223,7 +223,7 @@ function BudgetTable({ files, onSelect, onDelete }) {
 }
 
 function RefreshButton({ onRefresh }) {
-  let [loading, setLoading] = useState(false);
+  const [loading, setLoading] = useState(false);
 
   async function _onRefresh() {
     setLoading(true);
@@ -231,7 +231,7 @@ function RefreshButton({ onRefresh }) {
     setLoading(false);
   }
 
-  let Icon = loading ? Loading : RefreshArrow;
+  const Icon = loading ? Loading : RefreshArrow;
 
   return (
     <Button
@@ -246,9 +246,9 @@ function RefreshButton({ onRefresh }) {
 }
 
 export default function BudgetList() {
-  let files = useSelector(state => state.budgets.allFiles || []);
+  const files = useSelector(state => state.budgets.allFiles || []);
 
-  let {
+  const {
     getUserData,
     loadAllFiles,
     pushModal,
diff --git a/packages/desktop-client/src/components/manager/ConfigServer.tsx b/packages/desktop-client/src/components/manager/ConfigServer.tsx
index cda664eb5..20cf42356 100644
--- a/packages/desktop-client/src/components/manager/ConfigServer.tsx
+++ b/packages/desktop-client/src/components/manager/ConfigServer.tsx
@@ -19,16 +19,16 @@ import { Title } from './subscribe/common';
 
 export default function ConfigServer() {
   useSetThemeColor(theme.mobileConfigServerViewTheme);
-  let { createBudget, signOut, loggedIn } = useActions();
-  let navigate = useNavigate();
-  let [url, setUrl] = useState('');
-  let currentUrl = useServerURL();
-  let setServerUrl = useSetServerURL();
+  const { createBudget, signOut, loggedIn } = useActions();
+  const navigate = useNavigate();
+  const [url, setUrl] = useState('');
+  const currentUrl = useServerURL();
+  const setServerUrl = useSetServerURL();
   useEffect(() => {
     setUrl(currentUrl);
   }, [currentUrl]);
-  let [loading, setLoading] = useState(false);
-  let [error, setError] = useState<string | null>(null);
+  const [loading, setLoading] = useState(false);
+  const [error, setError] = useState<string | null>(null);
 
   function getErrorMessage(error: string) {
     switch (error) {
@@ -46,14 +46,14 @@ export default function ConfigServer() {
 
     setError(null);
     setLoading(true);
-    let { error } = await setServerUrl(url);
+    const { error } = await setServerUrl(url);
 
     if (
       ['network-failure', 'get-server-failure'].includes(error) &&
       !url.startsWith('http://') &&
       !url.startsWith('https://')
     ) {
-      let { error } = await setServerUrl('https://' + url);
+      const { error } = await setServerUrl('https://' + url);
       if (error) {
         setUrl('https://' + url);
         setError(error);
diff --git a/packages/desktop-client/src/components/manager/DeleteFile.js b/packages/desktop-client/src/components/manager/DeleteFile.js
index 28eb1dc3f..a801fa346 100644
--- a/packages/desktop-client/src/components/manager/DeleteFile.js
+++ b/packages/desktop-client/src/components/manager/DeleteFile.js
@@ -7,7 +7,7 @@ import Text from '../common/Text';
 import View from '../common/View';
 
 export default function DeleteMenu({ modalProps, actions, file }) {
-  let [loadingState, setLoadingState] = useState(null);
+  const [loadingState, setLoadingState] = useState(null);
 
   async function onDeleteCloud() {
     setLoadingState('cloud');
@@ -28,7 +28,7 @@ export default function DeleteMenu({ modalProps, actions, file }) {
   // If the state is "broken" that means it was created by another
   // user. The current user should be able to delete the local file,
   // but not the remote one
-  let isRemote = file.cloudFileId && file.state !== 'broken';
+  const isRemote = file.cloudFileId && file.state !== 'broken';
 
   return (
     <Modal
diff --git a/packages/desktop-client/src/components/manager/Import.tsx b/packages/desktop-client/src/components/manager/Import.tsx
index 23854fe2c..823a565cd 100644
--- a/packages/desktop-client/src/components/manager/Import.tsx
+++ b/packages/desktop-client/src/components/manager/Import.tsx
@@ -41,7 +41,7 @@ function Import({ modalProps, actions }: ImportProps) {
     }
   }
 
-  let itemStyle = {
+  const itemStyle = {
     padding: 10,
     border: '1px solid ' + theme.tableBorder,
     borderRadius: 6,
diff --git a/packages/desktop-client/src/components/manager/ManagementApp.js b/packages/desktop-client/src/components/manager/ManagementApp.js
index 3e61c09b7..d72cf4141 100644
--- a/packages/desktop-client/src/components/manager/ManagementApp.js
+++ b/packages/desktop-client/src/components/manager/ManagementApp.js
@@ -48,13 +48,13 @@ function Version() {
 }
 
 export default function ManagementApp({ isLoading }) {
-  let files = useSelector(state => state.budgets.allFiles);
-  let userData = useSelector(state => state.user.data);
-  let managerHasInitialized = useSelector(
+  const files = useSelector(state => state.budgets.allFiles);
+  const userData = useSelector(state => state.user.data);
+  const managerHasInitialized = useSelector(
     state => state.app.managerHasInitialized,
   );
 
-  let { setAppState, getUserData, loadAllFiles } = useActions();
+  const { setAppState, getUserData, loadAllFiles } = useActions();
 
   // runs on mount only
   useEffect(() => {
@@ -74,7 +74,7 @@ export default function ManagementApp({ isLoading }) {
     }
 
     async function fetchData() {
-      let userData = await getUserData();
+      const userData = await getUserData();
       if (userData) {
         await loadAllFiles();
       }
diff --git a/packages/desktop-client/src/components/manager/Modals.js b/packages/desktop-client/src/components/manager/Modals.js
index fa6451658..cc7637a33 100644
--- a/packages/desktop-client/src/components/manager/Modals.js
+++ b/packages/desktop-client/src/components/manager/Modals.js
@@ -14,11 +14,11 @@ import ImportYNAB4 from './ImportYNAB4';
 import ImportYNAB5 from './ImportYNAB5';
 
 export default function Modals() {
-  let modalStack = useSelector(state => state.modals.modalStack);
-  let isHidden = useSelector(state => state.modals.isHidden);
-  let actions = useActions();
+  const modalStack = useSelector(state => state.modals.modalStack);
+  const isHidden = useSelector(state => state.modals.isHidden);
+  const actions = useActions();
 
-  let stack = modalStack.map(({ name, options = {} }, idx) => {
+  const stack = modalStack.map(({ name, options = {} }, idx) => {
     const modalProps = {
       onClose: actions.popModal,
       onPush: actions.pushModal,
diff --git a/packages/desktop-client/src/components/manager/WelcomeScreen.tsx b/packages/desktop-client/src/components/manager/WelcomeScreen.tsx
index 5f05c5cf5..89f45cf10 100644
--- a/packages/desktop-client/src/components/manager/WelcomeScreen.tsx
+++ b/packages/desktop-client/src/components/manager/WelcomeScreen.tsx
@@ -9,7 +9,7 @@ import Text from '../common/Text';
 import View from '../common/View';
 
 export default function WelcomeScreen() {
-  let { createBudget, pushModal } = useActions();
+  const { createBudget, pushModal } = useActions();
 
   return (
     <View
diff --git a/packages/desktop-client/src/components/manager/subscribe/Bootstrap.tsx b/packages/desktop-client/src/components/manager/subscribe/Bootstrap.tsx
index 0de5a81df..479833542 100644
--- a/packages/desktop-client/src/components/manager/subscribe/Bootstrap.tsx
+++ b/packages/desktop-client/src/components/manager/subscribe/Bootstrap.tsx
@@ -16,10 +16,10 @@ import { useBootstrapped, Title } from './common';
 import { ConfirmPasswordForm } from './ConfirmPasswordForm';
 
 export default function Bootstrap() {
-  let dispatch = useDispatch();
-  let [error, setError] = useState(null);
+  const dispatch = useDispatch();
+  const [error, setError] = useState(null);
 
-  let { checked } = useBootstrapped();
+  const { checked } = useBootstrapped();
 
   function getErrorMessage(error) {
     switch (error) {
@@ -36,7 +36,7 @@ export default function Bootstrap() {
 
   async function onSetPassword(password) {
     setError(null);
-    let { error } = await send('subscribe-bootstrap', { password });
+    const { error } = await send('subscribe-bootstrap', { password });
 
     if (error) {
       setError(error);
diff --git a/packages/desktop-client/src/components/manager/subscribe/ChangePassword.tsx b/packages/desktop-client/src/components/manager/subscribe/ChangePassword.tsx
index 68adb49b8..3988553ad 100644
--- a/packages/desktop-client/src/components/manager/subscribe/ChangePassword.tsx
+++ b/packages/desktop-client/src/components/manager/subscribe/ChangePassword.tsx
@@ -12,9 +12,9 @@ import { Title } from './common';
 import { ConfirmPasswordForm } from './ConfirmPasswordForm';
 
 export default function ChangePassword() {
-  let navigate = useNavigate();
-  let [error, setError] = useState(null);
-  let [msg, setMessage] = useState(null);
+  const navigate = useNavigate();
+  const [error, setError] = useState(null);
+  const [msg, setMessage] = useState(null);
 
   function getErrorMessage(error) {
     switch (error) {
@@ -31,7 +31,7 @@ export default function ChangePassword() {
 
   async function onSetPassword(password) {
     setError(null);
-    let { error } = await send('subscribe-change-password', { password });
+    const { error } = await send('subscribe-change-password', { password });
 
     if (error) {
       setError(error);
diff --git a/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx b/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx
index b0d5b3622..32ab5ca8a 100644
--- a/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx
+++ b/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx
@@ -5,10 +5,10 @@ import { BigInput } from '../../common/Input';
 import View from '../../common/View';
 
 export function ConfirmPasswordForm({ buttons, onSetPassword, onError }) {
-  let [password1, setPassword1] = useState('');
-  let [password2, setPassword2] = useState('');
-  let [showPassword, setShowPassword] = useState(false);
-  let [loading, setLoading] = useState(false);
+  const [password1, setPassword1] = useState('');
+  const [password2, setPassword2] = useState('');
+  const [showPassword, setShowPassword] = useState(false);
+  const [loading, setLoading] = useState(false);
 
   async function onSubmit(e) {
     e.preventDefault();
diff --git a/packages/desktop-client/src/components/manager/subscribe/Error.tsx b/packages/desktop-client/src/components/manager/subscribe/Error.tsx
index 30429f89f..a26ff87c6 100644
--- a/packages/desktop-client/src/components/manager/subscribe/Error.tsx
+++ b/packages/desktop-client/src/components/manager/subscribe/Error.tsx
@@ -17,9 +17,9 @@ function getErrorMessage(reason) {
 }
 
 export default function Error() {
-  let navigate = useNavigate();
-  let location = useLocation();
-  let { error } = (location.state || {}) as { error? };
+  const navigate = useNavigate();
+  const location = useLocation();
+  const { error } = (location.state || {}) as { error? };
 
   function onTryAgain() {
     navigate('/');
diff --git a/packages/desktop-client/src/components/manager/subscribe/Login.tsx b/packages/desktop-client/src/components/manager/subscribe/Login.tsx
index 600c80966..3ed5cef99 100644
--- a/packages/desktop-client/src/components/manager/subscribe/Login.tsx
+++ b/packages/desktop-client/src/components/manager/subscribe/Login.tsx
@@ -14,12 +14,12 @@ import View from '../../common/View';
 import { useBootstrapped, Title } from './common';
 
 export default function Login() {
-  let dispatch = useDispatch();
-  let [password, setPassword] = useState('');
-  let [loading, setLoading] = useState(false);
-  let [error, setError] = useState(null);
+  const dispatch = useDispatch();
+  const [password, setPassword] = useState('');
+  const [loading, setLoading] = useState(false);
+  const [error, setError] = useState(null);
 
-  let { checked } = useBootstrapped();
+  const { checked } = useBootstrapped();
 
   function getErrorMessage(error) {
     switch (error) {
@@ -40,7 +40,7 @@ export default function Login() {
 
     setError(null);
     setLoading(true);
-    let { error } = await send('subscribe-sign-in', { password });
+    const { error } = await send('subscribe-sign-in', { password });
     setLoading(false);
 
     if (error) {
diff --git a/packages/desktop-client/src/components/manager/subscribe/common.tsx b/packages/desktop-client/src/components/manager/subscribe/common.tsx
index 9cc46ca8a..cb328c960 100644
--- a/packages/desktop-client/src/components/manager/subscribe/common.tsx
+++ b/packages/desktop-client/src/components/manager/subscribe/common.tsx
@@ -17,14 +17,14 @@ import { useSetServerURL } from '../../ServerContext';
 // they will also potentially redirect to other pages which do *not*
 // do any checks.
 export function useBootstrapped() {
-  let [checked, setChecked] = useState(false);
-  let navigate = useNavigate();
-  let location = useLocation();
-  let setServerURL = useSetServerURL();
+  const [checked, setChecked] = useState(false);
+  const navigate = useNavigate();
+  const location = useLocation();
+  const setServerURL = useSetServerURL();
 
   useEffect(() => {
     async function run() {
-      let ensure = url => {
+      const ensure = url => {
         if (location.pathname !== url) {
           navigate(url);
         } else {
@@ -32,12 +32,12 @@ export function useBootstrapped() {
         }
       };
 
-      let url = await send('get-server-url');
-      let bootstrapped = await send('get-did-bootstrap');
+      const url = await send('get-server-url');
+      const bootstrapped = await send('get-did-bootstrap');
       if (url == null && !bootstrapped) {
         // A server hasn't been specified yet
-        let serverURL = window.location.origin;
-        let result = await send('subscribe-needs-bootstrap', {
+        const serverURL = window.location.origin;
+        const result = await send('subscribe-needs-bootstrap', {
           url: serverURL,
         });
         if ('error' in result || !result.hasServer) {
@@ -54,7 +54,7 @@ export function useBootstrapped() {
           ensure('/bootstrap');
         }
       } else {
-        let result = await send('subscribe-needs-bootstrap');
+        const result = await send('subscribe-needs-bootstrap');
         if ('error' in result) {
           navigate('/error', { state: { error: result.error } });
         } else if (result.bootstrapped) {
diff --git a/packages/desktop-client/src/components/mobile/MobileAmountInput.js b/packages/desktop-client/src/components/mobile/MobileAmountInput.js
index a1c6895a5..4155bffab 100644
--- a/packages/desktop-client/src/components/mobile/MobileAmountInput.js
+++ b/packages/desktop-client/src/components/mobile/MobileAmountInput.js
@@ -132,7 +132,7 @@ class AmountInput extends PureComponent {
   };
 
   onChangeText = text => {
-    let { onChange } = this.props;
+    const { onChange } = this.props;
 
     this.setState({ text });
     onChange(text);
@@ -142,7 +142,7 @@ class AmountInput extends PureComponent {
     const { style, textStyle } = this.props;
     const { editing, value, text } = this.state;
 
-    let input = (
+    const input = (
       <input
         type="text"
         ref={el => (this.input = el)}
diff --git a/packages/desktop-client/src/components/modals/CloseAccount.tsx b/packages/desktop-client/src/components/modals/CloseAccount.tsx
index 48f63a61f..2b58b0852 100644
--- a/packages/desktop-client/src/components/modals/CloseAccount.tsx
+++ b/packages/desktop-client/src/components/modals/CloseAccount.tsx
@@ -51,12 +51,12 @@ function CloseAccount({
   actions,
   modalProps,
 }: CloseAccountProps) {
-  let [loading, setLoading] = useState(false);
-  let [transfer, setTransfer] = useState('');
-  let [category, setCategory] = useState('');
+  const [loading, setLoading] = useState(false);
+  const [transfer, setTransfer] = useState('');
+  const [category, setCategory] = useState('');
 
-  let [transferError, setTransferError] = useState(false);
-  let [categoryError, setCategoryError] = useState(false);
+  const [transferError, setTransferError] = useState(false);
+  const [categoryError, setCategoryError] = useState(false);
 
   return (
     <Modal
@@ -84,10 +84,10 @@ function CloseAccount({
             onSubmit={event => {
               event.preventDefault();
 
-              let transferError = balance !== 0 && transfer === '';
+              const transferError = balance !== 0 && transfer === '';
               setTransferError(transferError);
 
-              let categoryError =
+              const categoryError =
                 needsCategory(account, transfer, accounts) && category === '';
               setCategoryError(categoryError);
 
diff --git a/packages/desktop-client/src/components/modals/CreateEncryptionKey.tsx b/packages/desktop-client/src/components/modals/CreateEncryptionKey.tsx
index 33c8f94f0..8a18eff5f 100644
--- a/packages/desktop-client/src/components/modals/CreateEncryptionKey.tsx
+++ b/packages/desktop-client/src/components/modals/CreateEncryptionKey.tsx
@@ -30,19 +30,19 @@ export default function CreateEncryptionKey({
   actions,
   options = {},
 }: CreateEncryptionKeyProps) {
-  let [password, setPassword] = useState('');
-  let [loading, setLoading] = useState(false);
-  let [error, setError] = useState('');
-  let [showPassword, setShowPassword] = useState(false);
+  const [password, setPassword] = useState('');
+  const [loading, setLoading] = useState(false);
+  const [error, setError] = useState('');
+  const [showPassword, setShowPassword] = useState(false);
 
-  let isRecreating = options.recreate;
+  const isRecreating = options.recreate;
 
   async function onCreateKey() {
     if (password !== '' && !loading) {
       setLoading(true);
       setError(null);
 
-      let res = await send('key-make', { password });
+      const res = await send('key-make', { password });
       if (res.error) {
         setLoading(null);
         setError(getCreateKeyError(res.error));
diff --git a/packages/desktop-client/src/components/modals/CreateLocalAccount.tsx b/packages/desktop-client/src/components/modals/CreateLocalAccount.tsx
index 62d208cb3..5f5cc59e6 100644
--- a/packages/desktop-client/src/components/modals/CreateLocalAccount.tsx
+++ b/packages/desktop-client/src/components/modals/CreateLocalAccount.tsx
@@ -23,15 +23,15 @@ type CreateLocalAccountProps = {
 };
 
 function CreateLocalAccount({ modalProps, actions }: CreateLocalAccountProps) {
-  let navigate = useNavigate();
-  let [name, setName] = useState('');
-  let [offbudget, setOffbudget] = useState(false);
-  let [balance, setBalance] = useState('0');
+  const navigate = useNavigate();
+  const [name, setName] = useState('');
+  const [offbudget, setOffbudget] = useState(false);
+  const [balance, setBalance] = useState('0');
 
-  let [nameError, setNameError] = useState(false);
-  let [balanceError, setBalanceError] = useState(false);
+  const [nameError, setNameError] = useState(false);
+  const [balanceError, setBalanceError] = useState(false);
 
-  let validateBalance = balance => !isNaN(parseFloat(balance));
+  const validateBalance = balance => !isNaN(parseFloat(balance));
 
   return (
     <Modal title="Create Local Account" {...modalProps}>
@@ -41,15 +41,15 @@ function CreateLocalAccount({ modalProps, actions }: CreateLocalAccountProps) {
             onSubmit={async event => {
               event.preventDefault();
 
-              let nameError = !name;
+              const nameError = !name;
               setNameError(nameError);
 
-              let balanceError = !validateBalance(balance);
+              const balanceError = !validateBalance(balance);
               setBalanceError(balanceError);
 
               if (!nameError && !balanceError) {
                 actions.closeModal();
-                let id = await actions.createAccount(
+                const id = await actions.createAccount(
                   name,
                   toRelaxedNumber(balance),
                   offbudget,
@@ -65,7 +65,7 @@ function CreateLocalAccount({ modalProps, actions }: CreateLocalAccountProps) {
                   value={name}
                   onChange={event => setName(event.target.value)}
                   onBlur={event => {
-                    let name = event.target.value.trim();
+                    const name = event.target.value.trim();
                     setName(name);
                     if (name && nameError) {
                       setNameError(false);
@@ -139,7 +139,7 @@ function CreateLocalAccount({ modalProps, actions }: CreateLocalAccountProps) {
                 value={balance}
                 onChange={event => setBalance(event.target.value)}
                 onBlur={event => {
-                  let balance = event.target.value.trim();
+                  const balance = event.target.value.trim();
                   setBalance(balance);
                   if (validateBalance(balance) && balanceError) {
                     setBalanceError(false);
diff --git a/packages/desktop-client/src/components/modals/EditField.js b/packages/desktop-client/src/components/modals/EditField.js
index e5a3dd365..853c85534 100644
--- a/packages/desktop-client/src/components/modals/EditField.js
+++ b/packages/desktop-client/src/components/modals/EditField.js
@@ -35,14 +35,14 @@ function CreatePayeeIcon(props) {
 }
 
 export default function EditField({ modalProps, name, onSubmit }) {
-  let dateFormat = useSelector(
+  const dateFormat = useSelector(
     state => state.prefs.local.dateFormat || 'MM/dd/yyyy',
   );
-  let { grouped: categoryGroups } = useCategories();
-  let accounts = useSelector(state => state.queries.accounts);
-  let payees = useSelector(state => state.queries.payees);
+  const { grouped: categoryGroups } = useCategories();
+  const accounts = useSelector(state => state.queries.accounts);
+  const payees = useSelector(state => state.queries.payees);
 
-  let { createPayee } = useActions();
+  const { createPayee } = useActions();
 
   function onSelect(value) {
     if (value != null) {
@@ -65,18 +65,18 @@ export default function EditField({ modalProps, name, onSubmit }) {
 
   const { isNarrowWidth } = useResponsive();
   let label, editor, minWidth;
-  let inputStyle = {
+  const inputStyle = {
     ':focus': { boxShadow: 0 },
     ...(isNarrowWidth && itemStyle),
   };
-  let autocompleteProps = {
+  const autocompleteProps = {
     inputProps: { style: inputStyle },
     containerProps: { style: { height: isNarrowWidth ? '90vh' : 275 } },
   };
 
   switch (name) {
     case 'date': {
-      let today = currentDay();
+      const today = currentDay();
       label = 'Date';
       minWidth = 350;
       editor = (
diff --git a/packages/desktop-client/src/components/modals/EditRule.js b/packages/desktop-client/src/components/modals/EditRule.js
index 1af0c6e29..9893fa71f 100644
--- a/packages/desktop-client/src/components/modals/EditRule.js
+++ b/packages/desktop-client/src/components/modals/EditRule.js
@@ -54,7 +54,7 @@ function applyErrors(array, errorsArray) {
 }
 
 function getTransactionFields(conditions, actions) {
-  let fields = ['date'];
+  const fields = ['date'];
 
   if (conditions.find(c => c.field === 'imported_payee')) {
     fields.push('imported_payee');
@@ -191,8 +191,9 @@ function ConditionEditor({
   onDelete,
   onAdd,
 }) {
-  let { field, op, value, type, options, error } = condition;
+  const { field: originalField, op, value, type, options, error } = condition;
 
+  let field = originalField;
   if (field === 'amount' && options) {
     if (options.inflow) {
       field = 'amount-inflow';
@@ -251,10 +252,10 @@ function formatAmount(amount) {
 }
 
 function ScheduleDescription({ id }) {
-  let dateFormat = useSelector(state => {
+  const dateFormat = useSelector(state => {
     return state.prefs.local.dateFormat || 'MM/dd/yyyy';
   });
-  let scheduleData = useSchedules({
+  const scheduleData = useSchedules({
     transform: useCallback(q => q.filter({ id }), []),
   });
 
@@ -266,8 +267,8 @@ function ScheduleDescription({ id }) {
     return <View style={{ flex: 1 }}>{id}</View>;
   }
 
-  let [schedule] = scheduleData.schedules;
-  let status = schedule && scheduleData.statuses.get(schedule.id);
+  const [schedule] = scheduleData.schedules;
+  const status = schedule && scheduleData.statuses.get(schedule.id);
 
   return (
     <View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }}>
@@ -300,7 +301,7 @@ function ScheduleDescription({ id }) {
   );
 }
 
-let actionFields = [
+const actionFields = [
   'category',
   'payee',
   'notes',
@@ -310,7 +311,7 @@ let actionFields = [
   'amount',
 ].map(field => [field, mapField(field)]);
 function ActionEditor({ ops, action, editorStyle, onChange, onDelete, onAdd }) {
-  let { field, op, value, type, error, inputKey = 'initial' } = action;
+  const { field, op, value, type, error, inputKey = 'initial' } = action;
 
   return (
     <Editor style={editorStyle} error={error}>
@@ -364,7 +365,7 @@ function ActionEditor({ ops, action, editorStyle, onChange, onDelete, onAdd }) {
 }
 
 function StageInfo() {
-  let [open, setOpen] = useState();
+  const [open, setOpen] = useState();
 
   return (
     <View style={{ position: 'relative', marginLeft: 5 }}>
@@ -439,9 +440,9 @@ function ConditionsList({
         f => !conditions.some(c => c.field.includes(f) || f.includes(c.field)),
       );
     }
-    let field = fields[0] || 'payee';
+    const field = fields[0] || 'payee';
 
-    let copy = [...conditions];
+    const copy = [...conditions];
     copy.splice(index + 1, 0, {
       type: FIELD_TYPES.get(field),
       field,
@@ -463,7 +464,7 @@ function ConditionsList({
     onChangeConditions(
       updateValue(conditions, cond, () => {
         if (field === 'field') {
-          let newCond = { field: value };
+          const newCond = { field: value };
 
           if (value === 'amount-inflow') {
             newCond.field = 'amount';
@@ -475,7 +476,7 @@ function ConditionsList({
 
           newCond.type = FIELD_TYPES.get(newCond.field);
 
-          let prevType = FIELD_TYPES.get(cond.field);
+          const prevType = FIELD_TYPES.get(cond.field);
           if (
             (prevType === 'string' || prevType === 'number') &&
             prevType === newCond.type &&
@@ -490,7 +491,7 @@ function ConditionsList({
             return newInput(makeValue(null, newCond));
           }
         } else if (field === 'op') {
-          let op = value;
+          const op = value;
 
           // Switching between oneOf and other operators is a
           // special-case. It changes the input type, so we need to
@@ -589,7 +590,7 @@ function ConditionsList({
 // TODO:
 // * Dont touch child transactions?
 
-let conditionFields = [
+const conditionFields = [
   'imported_payee',
   'account',
   'category',
@@ -609,15 +610,17 @@ export default function EditRule({
   defaultRule,
   onSave: originalOnSave,
 }) {
-  let [conditions, setConditions] = useState(defaultRule.conditions.map(parse));
-  let [actions, setActions] = useState(defaultRule.actions.map(parse));
-  let [stage, setStage] = useState(defaultRule.stage);
-  let [conditionsOp, setConditionsOp] = useState(defaultRule.conditionsOp);
-  let [transactions, setTransactions] = useState([]);
-  let dispatch = useDispatch();
-  let scrollableEl = useRef();
+  const [conditions, setConditions] = useState(
+    defaultRule.conditions.map(parse),
+  );
+  const [actions, setActions] = useState(defaultRule.actions.map(parse));
+  const [stage, setStage] = useState(defaultRule.stage);
+  const [conditionsOp, setConditionsOp] = useState(defaultRule.conditionsOp);
+  const [transactions, setTransactions] = useState([]);
+  const dispatch = useDispatch();
+  const scrollableEl = useRef();
 
-  let isSchedule = actions.some(action => action.op === 'link-schedule');
+  const isSchedule = actions.some(action => action.op === 'link-schedule');
 
   useEffect(() => {
     dispatch(initiallyLoadPayees());
@@ -630,21 +633,21 @@ export default function EditRule({
   useEffect(() => {
     // Flash the scrollbar
     if (scrollableEl.current) {
-      let el = scrollableEl.current;
-      let top = el.scrollTop;
+      const el = scrollableEl.current;
+      const top = el.scrollTop;
       el.scrollTop = top + 1;
       el.scrollTop = top;
     }
 
     // Run it here
     async function run() {
-      let { filters } = await send('make-filters-from-conditions', {
+      const { filters } = await send('make-filters-from-conditions', {
         conditions: conditions.map(unparse),
       });
 
       if (filters.length > 0) {
         const conditionsOpKey = conditionsOp === 'or' ? '$or' : '$and';
-        let { data: transactions } = await runQuery(
+        const { data: transactions } = await runQuery(
           q('transactions')
             .filter({ [conditionsOpKey]: filters })
             .select('*'),
@@ -657,7 +660,7 @@ export default function EditRule({
     run();
   }, [actions, conditions, conditionsOp]);
 
-  let selectedInst = useSelected('transactions', transactions, []);
+  const selectedInst = useSelected('transactions', transactions, []);
 
   function addInitialAction() {
     addAction(-1);
@@ -665,12 +668,12 @@ export default function EditRule({
 
   function addAction(index) {
     let fields = actionFields.map(f => f[0]);
-    for (let action of actions) {
+    for (const action of actions) {
       fields = fields.filter(f => f !== action.field);
     }
-    let field = fields[0] || 'category';
+    const field = fields[0] || 'category';
 
-    let copy = [...actions];
+    const copy = [...actions];
     copy.splice(index + 1, 0, {
       type: FIELD_TYPES.get(field),
       field,
@@ -683,7 +686,7 @@ export default function EditRule({
   function onChangeAction(action, field, value) {
     setActions(
       updateValue(actions, action, () => {
-        let a = { ...action };
+        const a = { ...action };
         a[field] = value;
 
         if (field === 'field') {
@@ -724,7 +727,7 @@ export default function EditRule({
   }
 
   async function onSave() {
-    let rule = {
+    const rule = {
       ...defaultRule,
       stage,
       conditionsOp,
@@ -732,8 +735,8 @@ export default function EditRule({
       actions: actions.map(unparse),
     };
 
-    let method = rule.id ? 'rule-update' : 'rule-add';
-    let { error, id: newId } = await send(method, rule);
+    const method = rule.id ? 'rule-update' : 'rule-add';
+    const { error, id: newId } = await send(method, rule);
 
     if (error) {
       if (error.conditionErrors) {
@@ -754,7 +757,7 @@ export default function EditRule({
     }
   }
 
-  let editorStyle = {
+  const editorStyle = {
     color: theme.pillText,
     backgroundColor: theme.pillBackground,
     borderRadius: 4,
diff --git a/packages/desktop-client/src/components/modals/FixEncryptionKey.tsx b/packages/desktop-client/src/components/modals/FixEncryptionKey.tsx
index d327898f9..c7e0d9636 100644
--- a/packages/desktop-client/src/components/modals/FixEncryptionKey.tsx
+++ b/packages/desktop-client/src/components/modals/FixEncryptionKey.tsx
@@ -27,19 +27,19 @@ export default function FixEncryptionKey({
   actions,
   options = {},
 }: FixEncryptionKeyProps) {
-  let { hasExistingKey, cloudFileId, onSuccess } = options;
+  const { hasExistingKey, cloudFileId, onSuccess } = options;
 
-  let [password, setPassword] = useState('');
-  let [error, setError] = useState('');
-  let [loading, setLoading] = useState(false);
-  let [showPassword, setShowPassword] = useState(false);
+  const [password, setPassword] = useState('');
+  const [error, setError] = useState('');
+  const [loading, setLoading] = useState(false);
+  const [showPassword, setShowPassword] = useState(false);
 
   async function onUpdateKey() {
     if (password !== '' && !loading) {
       setLoading(true);
       setError(null);
 
-      let { error } = await send('key-test', {
+      const { error } = await send('key-test', {
         password,
         fileId: cloudFileId,
       });
diff --git a/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx b/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx
index 53355f336..ccdcad5a0 100644
--- a/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx
+++ b/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx
@@ -93,16 +93,16 @@ export default function GoCardlessExternalMsg({
 }: GoCardlessExternalMsgProps) {
   const dispatch = useDispatch();
 
-  let [waiting, setWaiting] = useState<string | null>(null);
-  let [success, setSuccess] = useState<boolean>(false);
-  let [institutionId, setInstitutionId] = useState<string>();
-  let [country, setCountry] = useState<string>();
-  let [error, setError] = useState<'unknown' | 'timeout' | null>(null);
-  let [isGoCardlessSetupComplete, setIsGoCardlessSetupComplete] = useState<
+  const [waiting, setWaiting] = useState<string | null>(null);
+  const [success, setSuccess] = useState<boolean>(false);
+  const [institutionId, setInstitutionId] = useState<string>();
+  const [country, setCountry] = useState<string>();
+  const [error, setError] = useState<'unknown' | 'timeout' | null>(null);
+  const [isGoCardlessSetupComplete, setIsGoCardlessSetupComplete] = useState<
     boolean | null
   >(null);
-  let [menuOpen, setMenuOpen] = useState<boolean>(false);
-  let data = useRef<GoCardlessToken | null>(null);
+  const [menuOpen, setMenuOpen] = useState<boolean>(false);
+  const data = useRef<GoCardlessToken | null>(null);
 
   const {
     data: bankOptions,
@@ -116,7 +116,7 @@ export default function GoCardlessExternalMsg({
     setError(null);
     setWaiting('browser');
 
-    let res = await onMoveExternal({ institutionId });
+    const res = await onMoveExternal({ institutionId });
     if (res.error) {
       setError(res.error);
       setWaiting(null);
diff --git a/packages/desktop-client/src/components/modals/ImportTransactions.js b/packages/desktop-client/src/components/modals/ImportTransactions.js
index 11665ea71..b66597e11 100644
--- a/packages/desktop-client/src/components/modals/ImportTransactions.js
+++ b/packages/desktop-client/src/components/modals/ImportTransactions.js
@@ -23,7 +23,7 @@ import View from '../common/View';
 import { Checkbox, SectionLabel } from '../forms';
 import { TableHeader, TableWithNavigator, Row, Field } from '../table';
 
-let dateFormats = [
+const dateFormats = [
   { format: 'yyyy mm dd', label: 'YYYY MM DD' },
   { format: 'yy mm dd', label: 'YY MM DD' },
   { format: 'mm dd yyyy', label: 'MM DD YYYY' },
@@ -108,7 +108,7 @@ export function parseDate(str, order) {
       day = parts[1];
   }
 
-  let parsed = `${year}-${pad(month)}-${pad(day)}`;
+  const parsed = `${year}-${pad(month)}-${pad(day)}`;
   if (!d.isValid(d.parseISO(parsed))) {
     return null;
   }
@@ -126,15 +126,15 @@ function formatDate(date, format) {
 }
 
 function getFileType(filepath) {
-  let m = filepath.match(/\.([^.]*)$/);
+  const m = filepath.match(/\.([^.]*)$/);
   if (!m) return 'ofx';
-  let rawType = m[1].toLowerCase();
+  const rawType = m[1].toLowerCase();
   if (rawType === 'tsv') return 'csv';
   return rawType;
 }
 
 function ParsedDate({ parseDateFormat, showParsed, dateFormat, date }) {
-  let parsed =
+  const parsed =
     date &&
     formatDate(
       parseDateFormat ? parseDate(date, parseDateFormat) : date,
@@ -162,10 +162,10 @@ function getInitialDateFormat(transactions, mappings) {
     return 'yyyy mm dd';
   }
 
-  let transaction = transactions[0];
-  let date = transaction[mappings.date];
+  const transaction = transactions[0];
+  const date = transaction[mappings.date];
 
-  let found =
+  const found =
     date == null
       ? null
       : dateFormats.find(f => parseDate(date, f.format) != null);
@@ -177,35 +177,35 @@ function getInitialMappings(transactions) {
     return {};
   }
 
-  let transaction = transactions[0];
-  let fields = Object.entries(transaction);
+  const transaction = transactions[0];
+  const fields = Object.entries(transaction);
 
   function key(entry) {
     return entry ? entry[0] : null;
   }
 
-  let dateField = key(
+  const dateField = key(
     fields.find(([name, value]) => name.toLowerCase().includes('date')) ||
       fields.find(([name, value]) => value.match(/^\d+[-/]\d+[-/]\d+$/)),
   );
 
-  let amountField = key(
+  const amountField = key(
     fields.find(([name, value]) => name.toLowerCase().includes('amount')) ||
       fields.find(([name, value]) => value.match(/^-?[.,\d]+$/)),
   );
 
-  let payeeField = key(
+  const payeeField = key(
     fields.find(([name, value]) => name !== dateField && name !== amountField),
   );
 
-  let notesField = key(
+  const notesField = key(
     fields.find(
       ([name, value]) =>
         name !== dateField && name !== amountField && name !== payeeField,
     ),
   );
 
-  let inOutField = key(
+  const inOutField = key(
     fields.find(
       ([name, value]) =>
         name !== dateField &&
@@ -225,8 +225,9 @@ function getInitialMappings(transactions) {
 }
 
 function applyFieldMappings(transaction, mappings) {
-  let result = {};
-  for (let [field, target] of Object.entries(mappings)) {
+  const result = {};
+  for (const [originalField, target] of Object.entries(mappings)) {
+    let field = originalField;
     if (field === 'payee') {
       field = 'payee_name';
     }
@@ -240,8 +241,9 @@ function parseAmount(amount, mapper) {
   if (amount == null) {
     return null;
   }
-  let parsed = typeof amount === 'string' ? looselyParseAmount(amount) : amount;
-  let value = mapper(parsed);
+  const parsed =
+    typeof amount === 'string' ? looselyParseAmount(amount) : amount;
+  const value = mapper(parsed);
   return value;
 }
 
@@ -259,8 +261,8 @@ function parseAmountFields(
     // Split mode is a little weird; first we look for an outflow and
     // if that has a value, we never want to show a number in the
     // inflow. Same for `amount`; we choose outflow first and then inflow
-    let outflow = parseAmount(trans.outflow, n => -Math.abs(n)) * multiplier;
-    let inflow = outflow
+    const outflow = parseAmount(trans.outflow, n => -Math.abs(n)) * multiplier;
+    const inflow = outflow
       ? 0
       : parseAmount(trans.inflow, n => Math.abs(n)) * multiplier;
 
@@ -300,7 +302,7 @@ function Transaction({
   flipAmount,
   multiplierAmount,
 }) {
-  let transaction = useMemo(
+  const transaction = useMemo(
     () =>
       fieldMappings
         ? applyFieldMappings(rawTransaction, fieldMappings)
@@ -434,8 +436,8 @@ function DateFormatSelect({
   // to space if we can't figure it out.
   let delimiter = '-';
   if (transactions.length > 0 && fieldMappings && fieldMappings.date != null) {
-    let date = transactions[0][fieldMappings.date];
-    let m = date && date.match(/[/.,-/\\]/);
+    const date = transactions[0][fieldMappings.date];
+    const m = date && date.match(/[/.,-/\\]/);
     delimiter = m ? m[0] : ' ';
   }
 
@@ -555,7 +557,7 @@ function FieldMappings({
     return null;
   }
 
-  let options = Object.keys(transactions[0]);
+  const options = Object.keys(transactions[0]);
   mappings = mappings || {};
 
   return (
@@ -655,53 +657,53 @@ function FieldMappings({
 }
 
 export default function ImportTransactions({ modalProps, options }) {
-  let dateFormat = useSelector(
+  const dateFormat = useSelector(
     state => state.prefs.local.dateFormat || 'MM/dd/yyyy',
   );
-  let prefs = useSelector(state => state.prefs.local);
-  let { parseTransactions, importTransactions, getPayees, savePrefs } =
+  const prefs = useSelector(state => state.prefs.local);
+  const { parseTransactions, importTransactions, getPayees, savePrefs } =
     useActions();
 
-  let [multiplierAmount, setMultiplierAmount] = useState('');
-  let [loadingState, setLoadingState] = useState('parsing');
-  let [error, setError] = useState(null);
-  let [filename, setFilename] = useState(options.filename);
-  let [transactions, setTransactions] = useState([]);
-  let [filetype, setFileType] = useState(null);
-  let [fieldMappings, setFieldMappings] = useState(null);
-  let [splitMode, setSplitMode] = useState(false);
-  let [inOutMode, setInOutMode] = useState(false);
-  let [outValue, setOutValue] = useState('');
-  let [flipAmount, setFlipAmount] = useState(false);
-  let [multiplierEnabled, setMultiplierEnabled] = useState(false);
-  let { accountId, onImported } = options;
+  const [multiplierAmount, setMultiplierAmount] = useState('');
+  const [loadingState, setLoadingState] = useState('parsing');
+  const [error, setError] = useState(null);
+  const [filename, setFilename] = useState(options.filename);
+  const [transactions, setTransactions] = useState([]);
+  const [filetype, setFileType] = useState(null);
+  const [fieldMappings, setFieldMappings] = useState(null);
+  const [splitMode, setSplitMode] = useState(false);
+  const [inOutMode, setInOutMode] = useState(false);
+  const [outValue, setOutValue] = useState('');
+  const [flipAmount, setFlipAmount] = useState(false);
+  const [multiplierEnabled, setMultiplierEnabled] = useState(false);
+  const { accountId, onImported } = options;
 
   // This cannot be set after parsing the file, because changing it
   // requires re-parsing the file. This is different from the other
   // options which are simple post-processing. That means if you
   // parsed different files without closing the modal, it wouldn't
   // re-read this.
-  let [delimiter, setDelimiter] = useState(
+  const [delimiter, setDelimiter] = useState(
     prefs[`csv-delimiter-${accountId}`] ||
       (filename.endsWith('.tsv') ? '\t' : ','),
   );
-  let [hasHeaderRow, setHasHeaderRow] = useState(
+  const [hasHeaderRow, setHasHeaderRow] = useState(
     prefs[`csv-has-header-${accountId}`] ?? true,
   );
-  let [fallbackMissingPayeeToMemo, setFallbackMissingPayeeToMemo] = useState(
+  const [fallbackMissingPayeeToMemo, setFallbackMissingPayeeToMemo] = useState(
     prefs[`ofx-fallback-missing-payee-${accountId}`] ?? true,
   );
 
-  let [parseDateFormat, setParseDateFormat] = useState(null);
+  const [parseDateFormat, setParseDateFormat] = useState(null);
 
-  let [clearOnImport, setClearOnImport] = useState(true);
+  const [clearOnImport, setClearOnImport] = useState(true);
 
   const enableExperimentalOfxParser = useFeatureFlag('experimentalOfxParser');
 
   async function parse(filename, options) {
     setLoadingState('parsing');
 
-    let filetype = getFileType(filename);
+    const filetype = getFileType(filename);
     setFilename(filename);
     setFileType(filetype);
 
@@ -710,7 +712,7 @@ export default function ImportTransactions({ modalProps, options }) {
       enableExperimentalOfxParser,
     };
 
-    let { errors, transactions } = await parseTransactions(filename, options);
+    const { errors, transactions } = await parseTransactions(filename, options);
     setLoadingState(null);
     setError(null);
 
@@ -734,7 +736,7 @@ export default function ImportTransactions({ modalProps, options }) {
         setFieldMappings(mappings);
 
         // Set initial split mode based on any saved mapping
-        let initialSplitMode = !!(mappings.outflow || mappings.inflow);
+        const initialSplitMode = !!(mappings.outflow || mappings.inflow);
         setSplitMode(initialSplitMode);
 
         setParseDateFormat(
@@ -785,16 +787,16 @@ export default function ImportTransactions({ modalProps, options }) {
       setFlipAmount(!flipAmount);
     }
 
-    let isSplit = !splitMode;
+    const isSplit = !splitMode;
     setSplitMode(isSplit);
     setInOutMode(false);
     setFlipAmount(false);
 
     // Run auto-detection on the fields to try to detect the fields
     // automatically
-    let mappings = getInitialMappings(transactions);
+    const mappings = getInitialMappings(transactions);
 
-    let newFieldMappings = isSplit
+    const newFieldMappings = isSplit
       ? {
           amount: null,
           outflow: mappings.amount,
@@ -835,13 +837,13 @@ export default function ImportTransactions({ modalProps, options }) {
   async function onImport() {
     setLoadingState('importing');
 
-    let finalTransactions = [];
+    const finalTransactions = [];
     let errorMessage;
 
     for (let trans of transactions) {
       trans = fieldMappings ? applyFieldMappings(trans, fieldMappings) : trans;
 
-      let date = isOfxFile(filetype)
+      const date = isOfxFile(filetype)
         ? trans.date
         : parseDate(trans.date, parseDateFormat);
       if (date == null) {
@@ -851,7 +853,7 @@ export default function ImportTransactions({ modalProps, options }) {
         break;
       }
 
-      let { amount } = parseAmountFields(
+      const { amount } = parseAmountFields(
         trans,
         splitMode,
         inOutMode,
@@ -864,7 +866,7 @@ export default function ImportTransactions({ modalProps, options }) {
         break;
       }
 
-      let { inflow, outflow, inOut, ...finalTransaction } = trans;
+      const { inflow, outflow, inOut, ...finalTransaction } = trans;
       finalTransactions.push({
         ...finalTransaction,
         date,
@@ -880,7 +882,7 @@ export default function ImportTransactions({ modalProps, options }) {
     }
 
     if (!isOfxFile(filetype)) {
-      let key = `parse-date-${accountId}-${filetype}`;
+      const key = `parse-date-${accountId}-${filetype}`;
       savePrefs({ [key]: parseDateFormat });
     }
 
@@ -901,7 +903,7 @@ export default function ImportTransactions({ modalProps, options }) {
       savePrefs({ [`flip-amount-${accountId}-${filetype}`]: flipAmount });
     }
 
-    let didChange = await importTransactions(accountId, finalTransactions);
+    const didChange = await importTransactions(accountId, finalTransactions);
     if (didChange) {
       await getPayees();
     }
@@ -913,7 +915,7 @@ export default function ImportTransactions({ modalProps, options }) {
     modalProps.onClose();
   }
 
-  let headers = [
+  const headers = [
     { name: 'Date', width: 200 },
     { name: 'Payee', width: 'flex' },
     { name: 'Notes', width: 'flex' },
diff --git a/packages/desktop-client/src/components/modals/LoadBackup.js b/packages/desktop-client/src/components/modals/LoadBackup.js
index 6e0f3d98e..64786e724 100644
--- a/packages/desktop-client/src/components/modals/LoadBackup.js
+++ b/packages/desktop-client/src/components/modals/LoadBackup.js
@@ -54,7 +54,7 @@ function LoadBackup({
   actions,
   modalProps,
 }) {
-  let [backups, setBackups] = useState([]);
+  const [backups, setBackups] = useState([]);
 
   useEffect(() => {
     send('backups-get', { id: budgetId }).then(setBackups);
diff --git a/packages/desktop-client/src/components/modals/ManageRulesModal.tsx b/packages/desktop-client/src/components/modals/ManageRulesModal.tsx
index 72a7d202a..59dccf84a 100644
--- a/packages/desktop-client/src/components/modals/ManageRulesModal.tsx
+++ b/packages/desktop-client/src/components/modals/ManageRulesModal.tsx
@@ -16,8 +16,8 @@ export default function ManageRulesModal({
   modalProps,
   payeeId,
 }: ManageRulesModalProps) {
-  let [loading, setLoading] = useState(true);
-  let location = useLocation();
+  const [loading, setLoading] = useState(true);
+  const location = useLocation();
   if (isNonProductionEnvironment()) {
     if (location.pathname !== '/payees') {
       throw new Error(
diff --git a/packages/desktop-client/src/components/modals/MergeUnusedPayees.js b/packages/desktop-client/src/components/modals/MergeUnusedPayees.js
index 50d3f36ec..d857cdd6a 100644
--- a/packages/desktop-client/src/components/modals/MergeUnusedPayees.js
+++ b/packages/desktop-client/src/components/modals/MergeUnusedPayees.js
@@ -12,27 +12,27 @@ import Paragraph from '../common/Paragraph';
 import Text from '../common/Text';
 import View from '../common/View';
 
-let highlightStyle = { color: theme.pageTextPositive };
+const highlightStyle = { color: theme.pageTextPositive };
 
 export default function MergeUnusedPayees({
   modalProps,
   payeeIds,
   targetPayeeId,
 }) {
-  let { payees: allPayees, modalStack } = useSelector(state => ({
+  const { payees: allPayees, modalStack } = useSelector(state => ({
     payees: state.queries.payees,
     modalStack: state.modals.modalStack,
   }));
-  let isEditingRule = !!modalStack.find(m => m.name === 'edit-rule');
-  let dispatch = useDispatch();
-  let [shouldCreateRule, setShouldCreateRule] = useState(true);
-  let flashRef = useRef(null);
+  const isEditingRule = !!modalStack.find(m => m.name === 'edit-rule');
+  const dispatch = useDispatch();
+  const [shouldCreateRule, setShouldCreateRule] = useState(true);
+  const flashRef = useRef(null);
 
   useEffect(() => {
     // Flash the scrollbar
     if (flashRef.current) {
-      let el = flashRef.current;
-      let top = el.scrollTop;
+      const el = flashRef.current;
+      const top = el.scrollTop;
       el.scrollTop = top + 1;
       el.scrollTop = top;
     }
@@ -44,10 +44,10 @@ export default function MergeUnusedPayees({
   //
   // TODO: I think a custom `useSelector` hook that doesn't bind would
   // be nice
-  let [payees] = useState(() =>
+  const [payees] = useState(() =>
     payeeIds.map(id => allPayees.find(p => p.id === id)),
   );
-  let targetPayee = allPayees.find(p => p.id === targetPayeeId);
+  const targetPayee = allPayees.find(p => p.id === targetPayeeId);
 
   if (!targetPayee) {
     return null;
@@ -61,7 +61,7 @@ export default function MergeUnusedPayees({
 
     let ruleId;
     if (shouldCreateRule && !isEditingRule) {
-      let id = await send('rule-add-payee-rename', {
+      const id = await send('rule-add-payee-rename', {
         fromNames: payees.map(p => p.name),
         to: targetPayee.id,
       });
@@ -74,10 +74,10 @@ export default function MergeUnusedPayees({
   }
 
   async function onMergeAndCreateRule() {
-    let ruleId = await onMerge();
+    const ruleId = await onMerge();
 
     if (ruleId) {
-      let rule = await send('rule-get', { id: ruleId });
+      const rule = await send('rule-get', { id: ruleId });
       dispatch(replaceModal('edit-rule', { rule }));
     }
   }
diff --git a/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx b/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx
index 1b19f09c3..e9146a7e0 100644
--- a/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx
+++ b/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx
@@ -33,16 +33,16 @@ export default function PlaidExternalMsg({
   onSuccess,
   onClose: originalOnClose,
 }: PlainExternalMsgProps) {
-  let [waiting, setWaiting] = useState(null);
-  let [success, setSuccess] = useState(false);
-  let [error, setError] = useState(null);
-  let data = useRef(null);
+  const [waiting, setWaiting] = useState(null);
+  const [success, setSuccess] = useState(false);
+  const [error, setError] = useState(null);
+  const data = useRef(null);
 
   async function onJump() {
     setError(null);
     setWaiting('browser');
 
-    let res = await onMoveExternal();
+    const res = await onMoveExternal();
     if (res.error) {
       setError(res.error);
       setWaiting(null);
diff --git a/upcoming-release-notes/2033.md b/upcoming-release-notes/2033.md
new file mode 100644
index 000000000..afd077096
--- /dev/null
+++ b/upcoming-release-notes/2033.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [joel-jeremy]
+---
+
+Apply ESLint prefer-const on components folder part 1
-- 
GitLab