Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove use of useActions #3911

Merged
merged 3 commits into from
Dec 10, 2024
Merged

Remove use of useActions #3911

merged 3 commits into from
Dec 10, 2024

Conversation

joel-jeremy
Copy link
Contributor

No description provided.

@actual-github-bot actual-github-bot bot changed the title Remove use of useActions [WIP] Remove use of useActions Nov 27, 2024
Copy link

netlify bot commented Nov 27, 2024

Deploy Preview for actualbudget ready!

Name Link
🔨 Latest commit 704ab01
🔍 Latest deploy log https://app.netlify.com/sites/actualbudget/deploys/67587c5e950fd20008b896e3
😎 Deploy Preview https://deploy-preview-3911.demo.actualbudget.org
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@joel-jeremy joel-jeremy changed the title [WIP] Remove use of useActions Remove use of useActions Nov 27, 2024
Copy link
Contributor

github-actions bot commented Nov 27, 2024

Bundle Stats — desktop-client

Hey there, this message comes from a GitHub action that helps you and reviewers to understand how these changes affect the size of this project's bundle.

As this PR is updated, I'll keep you updated on how the bundle size is impacted.

Total

Files count Total bundle size % Changed
10 5.47 MB → 5.47 MB (+362 B) +0.01%
Changeset
File Δ Size
node_modules/clsx/dist/clsx.js 🆕 +509 B 0 B → 509 B
node_modules/clsx/dist/clsx.js?commonjs-module 🆕 +27 B 0 B → 27 B
src/components/LoggedInUser.tsx 📈 +126 B (+4.50%) 2.73 kB → 2.85 kB
src/components/UpdateNotification.tsx 📈 +53 B (+1.47%) 3.53 kB → 3.58 kB
src/components/settings/index.tsx 📈 +70 B (+1.12%) 6.13 kB → 6.2 kB
src/components/Titlebar.tsx 📈 +50 B (+0.61%) 8.02 kB → 8.07 kB
src/components/manager/ConfigServer.tsx 📈 +23 B (+0.31%) 7.22 kB → 7.24 kB
src/components/manager/WelcomeScreen.tsx 📈 +12 B (+0.29%) 4.05 kB → 4.06 kB
src/components/settings/Reset.tsx 📈 +6 B (+0.26%) 2.24 kB → 2.25 kB
node_modules/react-grid-layout/build/ReactGridLayout.js 📉 -1 B (-0.00%) 24.96 kB → 24.96 kB
node_modules/react-grid-layout/build/GridItem.js 📉 -1 B (-0.00%) 21.49 kB → 21.49 kB
node_modules/react-grid-layout/build/components/WidthProvider.js 📉 -1 B (-0.02%) 5.22 kB → 5.22 kB
src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx 📉 -79 B (-0.26%) 30.12 kB → 30.04 kB
node_modules/clsx/dist/clsx.mjs 🔥 -368 B (-100%) 368 B → 0 B
node_modules/clsx/dist/clsx.mjs?commonjs-proxy 🔥 -64 B (-100%) 64 B → 0 B
View detailed bundle breakdown

Added

No assets were added

Removed

No assets were removed

Bigger

Asset File Size % Changed
static/js/index.js 3.45 MB → 3.45 MB (+256 B) +0.01%
static/js/wide.js 241.29 kB → 241.46 kB (+173 B) +0.07%

Smaller

Asset File Size % Changed
static/js/ReportRouter.js 1.52 MB → 1.52 MB (-67 B) -0.00%

Unchanged

Asset File Size % Changed
static/js/resize-observer.js 18.37 kB 0%
static/js/useAccountPreviewTransactions.js 1.63 kB 0%
static/js/indexeddb-main-thread-worker-e59fee74.js 13.5 kB 0%
static/js/workbox-window.prod.es5.js 5.69 kB 0%
static/js/narrow.js 82.99 kB 0%
static/js/BackgroundImage.js 122.29 kB 0%
static/js/AppliedFilters.js 21.91 kB 0%

Copy link
Contributor

github-actions bot commented Nov 27, 2024

Bundle Stats — loot-core

Hey there, this message comes from a GitHub action that helps you and reviewers to understand how these changes affect the size of this project's bundle.

As this PR is updated, I'll keep you updated on how the bundle size is impacted.

Total

Files count Total bundle size % Changed
1 1.32 MB 0%

Changeset

No files were changed

View detailed bundle breakdown

Added

No assets were added

Removed

No assets were removed

Bigger

No assets were bigger

Smaller

No assets were smaller

Unchanged

Asset File Size % Changed
kcab.worker.js 1.32 MB 0%

Copy link
Contributor

coderabbitai bot commented Nov 27, 2024

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/desktop-client/src/components/LoggedInUser.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-eslint-plugin".

(The package "eslint-plugin-eslint-plugin" was not found when loaded as a Node module from the directory "/packages/eslint-plugin-actual".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-eslint-plugin@latest --save-dev

The plugin "eslint-plugin-eslint-plugin" was referenced from the config file in "packages/eslint-plugin-actual/.eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

Walkthrough

The pull request introduces significant changes across multiple components in the desktop client application, transitioning from a custom useActions hook to the Redux useDispatch hook for action dispatching. This change affects the LoggedInUser, Titlebar, UpdateNotification, ConfigServer, WelcomeScreen, ImportTransactionsModal, Reset, and Settings components. Each component has been updated to directly dispatch actions such as getUserData, signOut, sync, updateApp, createBudget, and resetSync. The modifications include the removal of the useActions hook and the implementation of local functions that utilize dispatch for invoking actions. The updates streamline the action dispatching process, enhance clarity, and align with Redux best practices. Error handling logic remains largely unchanged, but the manner of invoking actions has been standardized across components. Overall, the changes improve the integration of Redux within the application, ensuring a consistent approach to state management.

Possibly related PRs

  • Add UncategorizedButton to mobile budget view #3326: The changes in the LoggedInUser component regarding the use of Redux's useDispatch hook may relate to the similar removal of the useActions hook in the SyncButton component within Titlebar.tsx, which also transitions to using useDispatch for action dispatching.

  • Add context menu's #3381: The context menu enhancements in the Account.tsx component may connect with the changes in the LoggedInUser component, as both involve updates to user interaction mechanisms and state management through hooks.

  • Fix wrong scheduled transfer payment direction on PWA #3402: The modifications in Account.tsx regarding transaction handling and state management may relate to the changes in LoggedInUser, as both components are involved in user interactions and state updates.

  • 🧪 improving rules test e2e stability #3512: The changes in ManageRules.tsx to streamline schedule management may connect with the updates in LoggedInUser, as both involve improving user interaction and state management.

  • enhance: context menu budget page positioning #3775: The context menu improvements in SidebarCategory.tsx and SidebarGroup.tsx may relate to the changes in LoggedInUser, as both involve enhancing user interactions through context menus and state management.

  • Use useNavigate instead of accessing window.__navigate #3904: The transition from window.__navigate to useNavigate in LoggedInUser.tsx aligns with the broader effort to improve navigation handling across components, including those in the context menu updates in other PRs.

Suggested labels

:sparkles: Merged

Suggested reviewers

  • youngcw

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Experiment)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (11)
packages/desktop-client/src/components/settings/Reset.tsx (1)

45-45: Consider adding TypeScript type for dispatch

The Redux integration looks good! For better type safety, consider explicitly typing the dispatch:

- const dispatch = useDispatch();
+ const dispatch = useDispatch<AppDispatch>();

This would require importing AppDispatch from your store configuration:

import { AppDispatch } from 'path/to/store';

Also applies to: 51-51

packages/desktop-client/src/components/UpdateNotification.tsx (3)

23-26: Consider memoizing the callback function

While the transition to useDispatch is good, consider memoizing the onRestart callback using useCallback to prevent unnecessary re-renders in child components that receive this as a prop.

  const dispatch = useDispatch();
- const onRestart = () => {
+ const onRestart = useCallback(() => {
    dispatch(updateApp());
- };
+ }, [dispatch]);

87-92: Enhance the comment documentation

While the state update logic is correct, consider improving the comment to better explain why we need to persist this flag for the entire session and its implications.

-  // Set a flag to never show an update notification again for this session
+  // Prevent update notifications from reappearing during this session to avoid
+  // repeatedly interrupting the user after they've dismissed it once

Line range hint 1-108: Consider splitting presentation and container components

The component currently handles both state management and presentation. Consider splitting it into:

  1. A container component handling Redux state and actions
  2. A presentational component focusing on the UI

This would improve maintainability and make the component more testable.

Example structure:

// UpdateNotificationContainer.tsx
export function UpdateNotificationContainer() {
  const dispatch = useDispatch();
  const updateInfo = useSelector((state: State) => state.app.updateInfo);
  // ... other hooks and handlers ...
  
  return <UpdateNotificationPresentation 
    updateInfo={updateInfo}
    onRestart={onRestart}
    onClose={() => dispatch(setAppState({...}))}
  />;
}

// UpdateNotificationPresentation.tsx
export function UpdateNotificationPresentation({ 
  updateInfo, 
  onRestart, 
  onClose 
}: Props) {
  // Pure presentation logic
}
packages/desktop-client/src/components/LoggedInUser.tsx (3)

37-41: Consider adding error handling to the initialization

While the async initialization is well-structured, it would be beneficial to handle potential errors during getUserData dispatch.

 async function init() {
-  await dispatch(getUserData());
+  try {
+    await dispatch(getUserData());
+  } catch (error) {
+    console.error('Failed to get user data:', error);
+    // Optionally show user-friendly error message
+  }
 }

44-46: LGTM! Consider adding type safety to onMenuSelect parameter

The action dispatches are well-implemented and properly handle async operations. One small improvement would be to add type safety to the menu selection handler.

- async function onMenuSelect(type) {
+ type MenuAction = 'change-password' | 'sign-in' | 'sign-out' | 'config-server';
+ async function onMenuSelect(type: MenuAction) {

Also applies to: 49-49, 61-61, 65-65, 68-68


useActions hook is still in use and needs attention

  • packages/desktop-client/src/hooks/useActions.ts: The hook itself still exists
  • packages/desktop-client/src/components/accounts/Account.tsx: Active usage of the hook
  • Two files still importing the type: index.tsx and global-events.ts

This component has successfully removed useActions, but there are remaining instances in the codebase that need to be addressed for complete migration.

🔗 Analysis chain

Line range hint 1-141: Verify complete removal of useActions

Let's ensure no traces of useActions remain in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining useActions usage in the codebase
rg "useActions" packages/desktop-client/src/

Length of output: 788

packages/desktop-client/src/components/settings/index.tsx (1)

137-143: Consider memoizing the loadPrefs dispatch

While the current implementation is functional, consider memoizing the loadPrefs dispatch to optimize performance:

+ const memoizedLoadPrefs = useCallback(() => {
+   dispatch(loadPrefs());
+ }, [dispatch]);

  useEffect(() => {
-   const unlisten = listen('prefs-updated', () => {
-     dispatch(loadPrefs());
-   });
+   const unlisten = listen('prefs-updated', memoizedLoadPrefs);

-   dispatch(loadPrefs());
+   memoizedLoadPrefs();
    return () => unlisten();
-  }, [dispatch]);
+  }, [memoizedLoadPrefs]);

This change would:

  • Prevent unnecessary re-creation of the callback on each render
  • Maintain consistent reference for the event listener
  • Follow React's optimization patterns for callbacks
packages/desktop-client/src/components/Titlebar.tsx (1)

196-206: Consider using useCallback to memoize onSync

Wrapping onSync with useCallback will prevent unnecessary re-creation of the function on each render. This optimization is beneficial since onSync is used in the dependency array of useHotkeys and passed to the Button component.

Apply this diff:

+import { useCallback } from 'react';
...
-const onSync = () => dispatch(sync());
+const onSync = useCallback(() => dispatch(sync()), [dispatch]);
packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx (2)

312-312: Consider excluding dispatch from dependency arrays

Including dispatch in the dependency array of useCallback hooks is generally unnecessary because dispatch is stable and doesn't change between renders. Excluding it can prevent unnecessary re-creations of the callback.


403-403: Consider excluding dispatch from dependency arrays

Similarly, you can remove dispatch from the dependency array in this useCallback hook to avoid unnecessary re-creations.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 22623ce and b514751.

⛔ Files ignored due to path filters (1)
  • upcoming-release-notes/3911.md is excluded by !**/*.md
📒 Files selected for processing (8)
  • packages/desktop-client/src/components/LoggedInUser.tsx (3 hunks)
  • packages/desktop-client/src/components/Titlebar.tsx (4 hunks)
  • packages/desktop-client/src/components/UpdateNotification.tsx (4 hunks)
  • packages/desktop-client/src/components/manager/ConfigServer.tsx (4 hunks)
  • packages/desktop-client/src/components/manager/WelcomeScreen.tsx (4 hunks)
  • packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx (7 hunks)
  • packages/desktop-client/src/components/settings/Reset.tsx (2 hunks)
  • packages/desktop-client/src/components/settings/index.tsx (3 hunks)
🔇 Additional comments (21)
packages/desktop-client/src/components/settings/Reset.tsx (1)

2-2: LGTM! Import changes align with Redux integration

The new imports correctly support the transition from useActions to Redux's useDispatch pattern.

Also applies to: 6-6

packages/desktop-client/src/components/manager/WelcomeScreen.tsx (3)

3-5: LGTM: Clean import organization

The new imports follow Redux best practices by directly importing the dispatch hook and actions.


16-16: LGTM: Proper Redux hook usage

The useDispatch hook is correctly implemented at the component level, aligning with Redux best practices.


82-82: LGTM: Clean action dispatch implementation

The button handlers have been correctly updated to use dispatch, maintaining the same functionality while following Redux patterns.

Let's verify that all useActions occurrences have been removed from this component:

Also applies to: 92-92, 95-99

✅ Verification successful

Verified: All useActions have been properly replaced with useDispatch

The component has been correctly migrated:

  • No instances of useActions remain in the file
  • useDispatch is properly imported and used
  • All button handlers correctly use dispatch for actions
  • The functionality remains equivalent with the new implementation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify no remaining useActions usage in this component
rg "useActions" "packages/desktop-client/src/components/manager/WelcomeScreen.tsx"

Length of output: 80


Script:

#!/bin/bash
# Let's verify the component's imports and usage patterns more thoroughly
cat "packages/desktop-client/src/components/manager/WelcomeScreen.tsx"

Length of output: 3339

packages/desktop-client/src/components/UpdateNotification.tsx (1)

3-3: LGTM! Clean import organization

The imports are well-organized and correctly transition from useActions to Redux's useDispatch, aligning with Redux best practices.

Also applies to: 5-5

packages/desktop-client/src/components/LoggedInUser.tsx (2)

4-4: LGTM! Clean Redux setup

The migration to direct Redux hooks and action imports follows best practices and improves code clarity.

Also applies to: 6-6


29-31: LGTM! Proper Redux hook usage

The dispatch hook is correctly initialized alongside the existing selector, maintaining component functionality while modernizing the implementation.

packages/desktop-client/src/components/settings/index.tsx (4)

2-2: LGTM: Clean migration to useDispatch

The addition of useDispatch import aligns with Redux best practices and the PR's objective to remove useActions.


7-7: LGTM: Direct action imports

Clean transition to importing actions directly, which is consistent with standard Redux patterns.


130-134: LGTM: Clean dispatch implementation

The dispatch initialization and handler implementation follow React best practices:

  • Proper hook usage with useDispatch
  • Clean handler wrapping for the closeBudget action

176-176: LGTM: Clean event handler binding

The Button correctly uses the new onCloseBudget handler, maintaining consistency with the dispatch pattern.

packages/desktop-client/src/components/manager/ConfigServer.tsx (4)

4-4: LGTM: Clean import changes for Redux migration

The import changes appropriately set up direct usage of Redux's useDispatch and action creators, aligning with the PR objective of removing useActions.

Also applies to: 6-6


26-26: LGTM: Proper Redux hook initialization

The useDispatch hook is correctly initialized at the component's top level, following Redux best practices.


81-81: LGTM: Proper Redux dispatch implementation

The transition to using dispatch is implemented correctly, maintaining the async/await pattern and proper action dispatching.

Also applies to: 108-108, 114-114


Line range hint 1-238: Verify complete removal of useActions

Let's verify that no instances of useActions remain in this file or related components.

✅ Verification successful

No instances of useActions found in ConfigServer.tsx

The file correctly uses useDispatch from react-redux and imports specific action creators (createBudget, loggedIn, signOut) from 'loot-core/client/actions'. There are no remaining instances of useActions in this file.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining useActions usage in the codebase
rg "useActions" --type ts --type tsx

# Search for any remaining imports from the actions file that might still use the old pattern
rg "from ['|\"].*actions['|\"]" --type ts --type tsx

Length of output: 151


Script:

#!/bin/bash
# Search for any remaining useActions usage in the file and related components
rg "useActions" "packages/desktop-client/src/components/manager/ConfigServer.tsx"

# Search for any remaining imports from actions in the file
rg "from ['\"].*actions['\"]" "packages/desktop-client/src/components/manager/ConfigServer.tsx"

Length of output: 255

packages/desktop-client/src/components/Titlebar.tsx (4)

3-3: LGTM!

Importing useDispatch from 'react-redux' is appropriate.


9-9: LGTM!

Importing the sync action from 'loot-core/client/actions' is correct.


112-112: LGTM!

Initializing dispatch using useDispatch() is appropriate.


228-228: LGTM!

Updating the onPress handler to use onSync is appropriate and aligns with the changes made.

packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx (2)

268-268: Ensure dispatched actions return promises when using await

When you use await dispatch(action), it assumes that the dispatched action returns a promise. Please verify that importPreviewTransactions returns a promise when dispatched. If it doesn't, the await keyword may not behave as expected.

Run the following script to confirm if importPreviewTransactions returns a promise:

✅ Verification successful

importPreviewTransactions correctly returns a promise when dispatched

The action creator importPreviewTransactions returns an async thunk that explicitly declares its return type as Promise<boolean>. The implementation shows it's using async/await syntax and returns a promise, making it safe to use with await dispatch(action).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if 'importPreviewTransactions' returns a promise when dispatched

# Find the definition of 'importPreviewTransactions'
ast-grep --pattern $'export function importPreviewTransactions($_, $_) {
  $$$
}'

# Look for 'async' keyword or promise return statements in the function definition
rg -A 5 'export function importPreviewTransactions' | rg 'async|return.*Promise'

Length of output: 1810


323-325: Confirm that parseTransactions returns a promise when dispatched

Similarly, ensure that parseTransactions returns a promise when dispatched. Using await on a non-promise value won't have the intended effect.

Run the following script to verify if parseTransactions returns a promise:

✅ Verification successful

parseTransactions is correctly implemented to return a promise when dispatched

The implementation in packages/loot-core/src/client/actions/account.ts shows that parseTransactions returns a thunk that is an async function, which in turn returns the result of an awaited send operation. This pattern ensures that when dispatched, it will indeed return a promise, making the await usage in the modal component correct and effective.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if 'parseTransactions' returns a promise when dispatched

# Find the definition of 'parseTransactions'
ast-grep --pattern $'export function parseTransactions($_, $_) {
  $$$
}'

# Look for 'async' keyword or promise return statements in the function definition
rg -A 5 'export function parseTransactions' | rg 'async|return.*Promise'

Length of output: 820

Comment on lines 114 to 115
await dispatch(createBudget({ testMode: true }));
window.__navigate('/');
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Inconsistent navigation approach detected

The code uses window.__navigate here while the rest of the component uses the useNavigate hook. Consider using the hook consistently:

-    window.__navigate('/');
+    navigate('/');

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good wabbit

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MikesGlitch, happy to help!

(^ ^)/

Comment on lines +656 to +660
const didChange = await dispatch(
importTransactions(accountId, finalTransactions, reconcile),
);
if (didChange) {
await getPayees();
await dispatch(getPayees());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for dispatched actions

When dispatching importTransactions and getPayees, consider adding error handling to manage potential exceptions. This ensures that your application can handle failures gracefully.

Apply this diff to add error handling:

+try {
  const didChange = await dispatch(
    importTransactions(accountId, finalTransactions, reconcile),
  );
  if (didChange) {
    await dispatch(getPayees());
  }
+} catch (error) {
+  // Handle the error appropriately
+  console.error('Error importing transactions:', error);
+  setError({ parsed: false, message: 'Failed to import transactions.' });
+  setLoadingState(null);
+}

Committable suggestion skipped: line range outside the PR's diff.

MikesGlitch
MikesGlitch previously approved these changes Nov 28, 2024
Copy link
Contributor

@MikesGlitch MikesGlitch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw you changed the navigate in another PR so LGTM

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (6)
packages/desktop-client/src/components/LoggedInUser.tsx (2)

39-43: Consider adding error handling to the init function

The async initialization could benefit from error handling to gracefully handle potential failures when fetching user data.

 async function init() {
+  try {
     await dispatch(getUserData());
+  } catch (error) {
+    console.error('Failed to fetch user data:', error);
+    // Consider showing a user-friendly error message
+  }
 }

46-48: Consider memoizing the onCloseBudget function

Since this function is passed as a prop and used in multiple places, it could benefit from memoization to prevent unnecessary re-renders.

-async function onCloseBudget() {
+const onCloseBudget = React.useCallback(async () => {
   await dispatch(closeBudget());
-}
+}, [dispatch]);
packages/desktop-client/src/components/settings/index.tsx (3)

1-7: Fix import order

The import of useNavigate should be moved before the import of style to maintain consistent import ordering.

 import React, { type ReactNode, useEffect } from 'react';
 import { useDispatch } from 'react-redux';
+import { useNavigate } from '../hooks/useNavigate';
 import { css } from '@emotion/css';
 import { t } from 'i18next';
 import { closeBudget, loadPrefs } from 'loot-core/client/actions';
-import { useNavigate } from '../hooks/useNavigate';

136-143: Improve effect cleanup handling

The effect should handle cleanup more gracefully by cancelling any pending operations.

 useEffect(() => {
+  let mounted = true;
   const unlisten = listen('prefs-updated', () => {
     dispatch(loadPrefs());
   });

-  dispatch(loadPrefs());
+  // Initial load
+  dispatch(loadPrefs()).catch(error => {
+    if (mounted) {
+      console.error('Failed to load preferences:', error);
+    }
+  });

-  return () => unlisten();
+  return () => {
+    mounted = false;
+    unlisten();
+  };
 }, [dispatch]);

132-134: Consider memoizing onCloseBudget

Since this function is used as a callback in event handlers, it should be memoized to prevent unnecessary re-renders.

-const onCloseBudget = () => {
+const onCloseBudget = React.useCallback(() => {
   dispatch(closeBudget());
-};
+}, [dispatch]);
packages/desktop-client/src/components/Titlebar.tsx (1)

Line range hint 112-228: Consider implementing a custom hook for sync logic

While the current implementation is correct, consider extracting the sync-related logic (state management, event listening, and dispatch) into a custom hook like useSyncHandler. This would improve reusability and make the component more focused on rendering.

Example structure:

function useSyncHandler() {
  const dispatch = useDispatch();
  const [syncing, setSyncing] = useState(false);
  const [syncState, setSyncState] = useState<SyncState>(null);

  useEffect(() => {
    // Current sync event listener logic
  }, []);

  const onSync = useCallback(() => dispatch(sync()), [dispatch]);

  return { syncing, syncState, onSync };
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between b514751 and d54b763.

⛔ Files ignored due to path filters (1)
  • upcoming-release-notes/3911.md is excluded by !**/*.md
📒 Files selected for processing (8)
  • packages/desktop-client/src/components/LoggedInUser.tsx (4 hunks)
  • packages/desktop-client/src/components/Titlebar.tsx (4 hunks)
  • packages/desktop-client/src/components/UpdateNotification.tsx (4 hunks)
  • packages/desktop-client/src/components/manager/ConfigServer.tsx (4 hunks)
  • packages/desktop-client/src/components/manager/WelcomeScreen.tsx (4 hunks)
  • packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx (7 hunks)
  • packages/desktop-client/src/components/settings/Reset.tsx (2 hunks)
  • packages/desktop-client/src/components/settings/index.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/desktop-client/src/components/settings/Reset.tsx
  • packages/desktop-client/src/components/UpdateNotification.tsx
  • packages/desktop-client/src/components/manager/ConfigServer.tsx
🧰 Additional context used
🪛 GitHub Check: lint
packages/desktop-client/src/components/LoggedInUser.tsx

[warning] 17-17:
../hooks/useNavigate import should occur before import of ../style

🔇 Additional comments (7)
packages/desktop-client/src/components/manager/WelcomeScreen.tsx (1)

3-5: LGTM! Clean transition to useDispatch

The changes correctly implement the Redux pattern by:

  1. Properly importing useDispatch and specific actions
  2. Consistently using dispatch for all action creators

Also applies to: 82-82, 92-92, 95-99

packages/desktop-client/src/components/Titlebar.tsx (3)

3-3: LGTM: Import changes align with Redux best practices

The new imports correctly set up the Redux dispatch functionality to replace the removed useActions hook.

Also applies to: 9-9


112-112: LGTM: Clean transition to Redux dispatch pattern

The changes effectively replace the useActions hook with Redux's useDispatch, maintaining the same functionality while following Redux best practices. The onSync function is properly memoized through the useHotkeys dependencies array.

Also applies to: 196-197, 206-206


228-228: LGTM: Button handler updated consistently

The onPress handler has been correctly updated to use the new onSync function, maintaining consistency with the Redux dispatch pattern.

packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx (3)

2-2: LGTM: Redux integration looks correct

The transition from useActions to useDispatch follows Redux best practices.

Also applies to: 146-146


312-312: LGTM: Dependencies are correctly updated

The dependency arrays for useCallback hooks have been properly updated to include the dispatch function.

Also applies to: 403-403


656-660: Verify the impact of transaction imports on payees

The code fetches payees after successful transaction import, but we should verify if this is always necessary.

✅ Verification successful

Let me gather more information about the importTransactions function to understand if it modifies payees.


Let me try a different approach to find the implementation and usage of importTransactions.


Let me check the implementation of the bank sync reconciliation which handles the transaction imports.


Let me check the normalization process of transactions to understand how payees are handled.


Based on the code analysis, I can now provide a definitive response about the necessity of fetching payees after transaction imports.

Fetching payees after transaction import is necessary

The code shows that new payees can be created during transaction imports through the following process:

  1. normalizeTransactions collects payees that need to be created in a payeesToCreate map
  2. resolvePayee function either finds existing payees or marks new ones for creation
  3. createNewPayees is called at the end of the import process to actually create the new payees in the database

Since new payees may be created during the import process, refreshing the payee list afterward ensures the UI has the latest payee data.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if imported transactions always affect payees
# Look for patterns where transactions might modify payee data

# Check for payee modifications in transaction imports
ast-grep --pattern 'importTransactions($$$) {
  $$$
  payee$$$
  $$$
}'

# Check for direct payee updates
rg -A 5 'updatePayee|createPayee|deletePayee'

Length of output: 9364


Script:

#!/bin/bash
# Check the implementation of importTransactions
ast-grep --pattern 'importTransactions($$$) {
  $$$
}'

# Check for any payee-related operations in transaction imports
rg -A 10 "import.*transaction" --type ts --type tsx --type js --type jsx

Length of output: 159


Script:

#!/bin/bash
# Search for importTransactions function definition and usage
rg -A 15 "importTransactions" --type js --type ts

# Look for transaction import related code that might modify payees
rg -A 10 "transaction.*import|import.*transaction" --type js --type ts

Length of output: 69894


Script:

#!/bin/bash
# Look for bank sync reconciliation code
rg -A 15 "reconcileTransactions" --type ts --type js

# Look for payee creation during transaction imports
rg -A 10 "createPayee.*transaction|transaction.*createPayee" --type ts --type js

Length of output: 25632


Script:

#!/bin/bash
# Look for transaction normalization code that handles payees
rg -A 15 "normalizeTransactions" --type ts --type js

# Look for payee creation during transaction processing
rg -A 15 "payeesToCreate" --type ts --type js

Length of output: 19367

Comment on lines +267 to +268
const previewTrx = await dispatch(
importPreviewTransactions(accountId, previewTransactions),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding error boundaries for dispatched actions

While the transition to useDispatch is correct, the error handling could be improved for the dispatched actions.

Apply this diff to add error handling:

-      const previewTrx = await dispatch(
-        importPreviewTransactions(accountId, previewTransactions),
-      );
+      let previewTrx;
+      try {
+        previewTrx = await dispatch(
+          importPreviewTransactions(accountId, previewTransactions),
+        );
+      } catch (error) {
+        console.error('Failed to preview transactions:', error);
+        setError({ parsed: false, message: 'Failed to preview transactions' });
+        setLoadingState(null);
+        return [];
+      }

-      const { errors, transactions: parsedTransactions = [] } = await dispatch(
-        parseTransactions(filename, options),
-      );
+      let result;
+      try {
+        result = await dispatch(parseTransactions(filename, options));
+      } catch (error) {
+        console.error('Failed to parse transactions:', error);
+        setError({ parsed: true, message: 'Failed to parse transactions' });
+        return { errors: [error], transactions: [] };
+      }
+      const { errors, transactions: parsedTransactions = [] } = result;

-    const didChange = await dispatch(
-      importTransactions(accountId, finalTransactions, reconcile),
-    );
-    if (didChange) {
-      await dispatch(getPayees());
-    }
+    try {
+      const didChange = await dispatch(
+        importTransactions(accountId, finalTransactions, reconcile),
+      );
+      if (didChange) {
+        await dispatch(getPayees());
+      }
+    } catch (error) {
+      console.error('Failed to import transactions:', error);
+      setError({ parsed: false, message: 'Failed to import transactions' });
+      setLoadingState(null);
+      return;
+    }

Also applies to: 323-325, 656-660

@joel-jeremy joel-jeremy force-pushed the remove-useActions-usage branch from b569392 to 704ab01 Compare December 10, 2024 17:37
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (2)
packages/desktop-client/src/components/settings/index.tsx (2)

130-134: Consider adding error handling for closeBudget action

While the transition to useDispatch is correct, consider adding error handling for the closeBudget action.

 const onCloseBudget = () => {
-  dispatch(closeBudget());
+  try {
+    dispatch(closeBudget());
+  } catch (error) {
+    console.error('Failed to close budget:', error);
+    // Consider showing user feedback
+  }
 };

138-143: Add error handling for loadPrefs action

The loadPrefs action in useEffect should include error handling.

 useEffect(() => {
   const unlisten = listen('prefs-updated', () => {
-    dispatch(loadPrefs());
+    try {
+      dispatch(loadPrefs());
+    } catch (error) {
+      console.error('Failed to load preferences:', error);
+      // Consider showing user feedback
+    }
   });

-  dispatch(loadPrefs());
+  try {
+    dispatch(loadPrefs());
+  } catch (error) {
+    console.error('Failed to load initial preferences:', error);
+    // Consider showing user feedback
+  }
   return () => unlisten();
 }, [dispatch]);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between b569392 and 704ab01.

⛔ Files ignored due to path filters (1)
  • upcoming-release-notes/3911.md is excluded by !**/*.md
📒 Files selected for processing (8)
  • packages/desktop-client/src/components/LoggedInUser.tsx (3 hunks)
  • packages/desktop-client/src/components/Titlebar.tsx (4 hunks)
  • packages/desktop-client/src/components/UpdateNotification.tsx (4 hunks)
  • packages/desktop-client/src/components/manager/ConfigServer.tsx (4 hunks)
  • packages/desktop-client/src/components/manager/WelcomeScreen.tsx (4 hunks)
  • packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx (7 hunks)
  • packages/desktop-client/src/components/settings/Reset.tsx (2 hunks)
  • packages/desktop-client/src/components/settings/index.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/desktop-client/src/components/LoggedInUser.tsx
  • packages/desktop-client/src/components/UpdateNotification.tsx
  • packages/desktop-client/src/components/manager/WelcomeScreen.tsx
  • packages/desktop-client/src/components/settings/Reset.tsx
  • packages/desktop-client/src/components/manager/ConfigServer.tsx
🔇 Additional comments (3)
packages/desktop-client/src/components/modals/ImportTransactionsModal/ImportTransactionsModal.jsx (3)

267-268: ⚠️ Potential issue

Add error handling for importPreviewTransactions

The importPreviewTransactions dispatch should include error handling.

This issue was previously identified in past reviews. The same error handling improvements are needed here.


323-325: ⚠️ Potential issue

Add error handling for parseTransactions

The parseTransactions dispatch should include error handling.

This issue was previously identified in past reviews. The same error handling improvements are needed here.


656-660: ⚠️ Potential issue

Add error handling for importTransactions and getPayees

The importTransactions and getPayees dispatches should include error handling.

This issue was previously identified in past reviews. The same error handling improvements are needed here.

Comment on lines +196 to +197
const onSync = () => dispatch(sync());

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling and loading state for sync action

The sync action should include error handling and potentially a loading state for better user feedback.

+const [isSyncing, setIsSyncing] = useState(false);
 const onSync = () => {
-  dispatch(sync());
+  setIsSyncing(true);
+  try {
+    dispatch(sync())
+      .then(() => {
+        // Consider showing success feedback
+      })
+      .catch((error) => {
+        console.error('Sync failed:', error);
+        // Consider showing error feedback
+      })
+      .finally(() => {
+        setIsSyncing(false);
+      });
+  } catch (error) {
+    console.error('Failed to initiate sync:', error);
+    setIsSyncing(false);
+  }
 };

Committable suggestion skipped: line range outside the PR's diff.

@joel-jeremy joel-jeremy merged commit 62d8358 into master Dec 10, 2024
20 checks passed
@joel-jeremy joel-jeremy deleted the remove-useActions-usage branch December 10, 2024 23:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants