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

fix: proper localstorage usage #5382

Closed
wants to merge 2 commits into from

Conversation

SukkaW
Copy link
Contributor

@SukkaW SukkaW commented Sep 7, 2024

💻 变更类型 | Change Type

  • feat
  • fix
  • refactor
  • perf
  • style
  • test
  • docs
  • ci
  • chore
  • build

🔀 变更说明 | Description of Change

image

I noticed a ReferenceError: localStorage is not defined error in my CI. The PR adds extra guards against localStorage access in the server/CI.

Summary by CodeRabbit

  • New Features

    • Introduced a new dependency, foxact, enhancing application functionality.
  • Improvements

    • Simplified local storage management for language filtering, improving readability and maintainability.
    • Enhanced robustness of storage functions to prevent errors in non-browser environments.
    • Added new hooks and utility functions for improved state management in React applications.
  • Bug Fixes

    • Updated handling of the absence of a language filter to ensure consistent representation across the application.

Copy link

vercel bot commented Sep 7, 2024

@SukkaW is attempting to deploy a commit to the NextChat Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

coderabbitai bot commented Sep 7, 2024

Walkthrough

The changes involve refactoring the MaskPage component to utilize a custom hook for local storage management, enhancing the handling of the filterLang state. Additionally, the code has been fortified against non-browser environments in both the locales and IndexedDBStorage modules, ensuring better robustness. A new dependency, foxact, has been added to the project, potentially expanding its capabilities.

Changes

Files Change Summary
app/components/mask.tsx Replaced local storage logic with useLocalStorage, changed filterLang type from undefined to null.
app/locales/index.ts Enhanced getItem and setItem functions with checks for non-browser environments.
app/utils/indexedDB-storage.ts Added checks in IndexedDBStorage methods to handle non-browser environments.
app/utils.ts Introduced useStorage hook, createStorage function, and noSSRError utility for improved storage management.
package.json Added new dependency "foxact": "^0.2.37".

Poem

In a world where code does hop,
A rabbit sings, "Oh, what a swap! 🐇
With filters clear and storage bright,
Our app now dances, pure delight!
No more errors, just smooth flow,
Thanks to changes, watch us grow!" 🌟


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>.
    • 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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @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 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

github-actions bot commented Sep 7, 2024

Your build has completed!

Preview deployment

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: 0

Outside diff range, codebase verification and nitpick comments (4)
app/utils/indexedDB-storage.ts (2)

6-8: Approve the environment check but suggest a minor improvement.

The addition of the environment check is a good practice to avoid errors in non-browser environments. However, consider logging or handling the scenario where window is undefined to aid in debugging or monitoring.


18-20: Approve the environment check and suggest a minor improvement.

The environment check is consistent and prevents errors in non-browser environments. Consider adding a log statement or a way to monitor these skipped operations for better observability.

app/locales/index.ts (2)

85-87: Approve the environment check and suggest handling other errors.

The addition of the environment check is a good practice to avoid errors in non-browser environments. Consider adding error handling for other potential localStorage issues to make the function more robust.


96-98: Approve the environment check and suggest handling other errors.

The addition of the environment check is a good practice to avoid errors in non-browser environments. Consider adding error handling for other potential localStorage issues to make the function more robust.

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 2ff292c and 4c84d63.

Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
Files selected for processing (4)
  • app/components/mask.tsx (3 hunks)
  • app/locales/index.ts (2 hunks)
  • app/utils/indexedDB-storage.ts (4 hunks)
  • package.json (1 hunks)
Files skipped from review due to trivial changes (1)
  • package.json
Additional comments not posted (3)
app/utils/indexedDB-storage.ts (2)

34-36: Approve the environment check.

The addition of the environment check is consistent with other methods and helps prevent errors in non-browser environments.


45-47: Approve the environment check.

The addition of the environment check is consistent with other methods and helps prevent errors in non-browser environments.

app/components/mask.tsx (1)

429-432: Approve the use of useLocalStorage and suggest verifying the impact of state change.

The refactoring to use useLocalStorage for managing filterLang state simplifies the code and improves maintainability. However, changing the state from undefined to null may affect other parts of the application. Verify that all components and functions that depend on filterLang handle the null value correctly.

Run the following script to verify the impact of the state change:

Also applies to: 540-540

Verification successful

The change from undefined to null for filterLang is handled correctly.

The instances of filterLang in the codebase show that null is appropriately managed. The filter function checks for falsy values, and the UI component sets filterLang to null under specific conditions, ensuring that the change does not introduce issues.

  • filterLang is used in a filter function with a condition that handles null.
  • The UI component sets filterLang to null when necessary.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all components and functions that depend on `filterLang` handle the `null` value correctly.

# Test: Search for the usage of `filterLang`. Expect: Proper handling of `null` value.
rg --type typescript -A 5 $'filterLang'

Length of output: 73


Script:

#!/bin/bash
# Description: Verify all components and functions that depend on `filterLang` handle the `null` value correctly.

# Test: Search for the usage of `filterLang`. Expect: Proper handling of `null` value.
rg --type ts -A 5 $'filterLang'

Length of output: 1099

@lloydzhou
Copy link
Contributor

我编译的时候看到这个报错信息了

但是这个并不影响整体逻辑,只是判断好组件在服务端运行导致的报错问题。

并不想因为这个引入额外的库

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


I saw this error message when compiling

However, this does not affect the overall logic, but only determines the error caused by the component running on the server.

I don’t want to introduce additional libraries because of this

@SukkaW
Copy link
Contributor Author

SukkaW commented Sep 7, 2024

我编译的时候看到这个报错信息了

但是这个并不影响整体逻辑,只是判断好组件在服务端运行导致的报错问题。

并不想因为这个引入额外的库

The extra library is for mask language only. The useState + using useEffect as watch is just a bad React practice.

@lloydzhou
Copy link
Contributor

image

鉴于前面提到的不想增加额外的包,这个pr里面应该,只有三个文件更改,不更改package.json以及yarn.lock
应该就没问题了

@SukkaW
Copy link
Contributor Author

SukkaW commented Sep 7, 2024

鉴于前面提到的不想增加额外的包,这个pr里面应该,只有三个文件更改,不更改package.json以及yarn.lock

Done in a0f11bf (#5382)

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, codebase verification and nitpick comments (1)
app/utils.ts (1)

412-621: Enhance Storage Handling with Custom Hooks

The createStorage function and the useStorage hook provide a robust mechanism for interacting with localStorage and sessionStorage. These utilities handle SSR scenarios gracefully by providing a fallback mechanism when window is undefined, which aligns with the PR's objectives to fix issues related to localStorage access in non-browser environments.

  • Pros: The code is modular and cleanly separates concerns between setting, getting, and removing storage items. It also dispatches custom events to handle storage changes, which is a good practice for reactive UI updates.
  • Cons: The complexity of the code has increased, which might impact maintainability. The use of custom events could be over-engineering if not utilized elsewhere in the application.

Consider simplifying the implementation if the custom events are not a necessary part of the application's architecture. Additionally, ensure that the documentation is updated to reflect these changes and guide developers on how to use these new hooks effectively.

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 4c84d63 and a0f11bf.

Files selected for processing (2)
  • app/components/mask.tsx (3 hunks)
  • app/utils.ts (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • app/components/mask.tsx
Additional context used
Biome
app/utils.ts

[error] 392-392: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)

Comment on lines +334 to +374
const useIsomorphicLayoutEffect =
typeof window !== "undefined" ? useLayoutEffect : useEffect;

const noop = () => {};

const stlProp = Object.getOwnPropertyDescriptor(Error, "stackTraceLimit");
const hasSTL = stlProp?.writable && typeof stlProp.value === "number";
const noSSRError = (
errorMessage?: string | undefined,
nextjsDigest = "BAILOUT_TO_CLIENT_SIDE_RENDERING",
) => {
const originalStackTraceLimit = Error.stackTraceLimit;

/**
* This is *only* safe to do when we know that nothing at any point in the
* stack relies on the `Error.stack` property of the noSSRError. By removing
* the strack trace of the error, we can improve the performance of object
* creation by a lot.
*/
if (hasSTL) {
Error.stackTraceLimit = 0;
}

const error = new Error(errorMessage);

/**
* Restore the stack trace limit to its original value after the error has
* been created.
*/
if (hasSTL) {
Error.stackTraceLimit = originalStackTraceLimit;
}

// Next.js marks errors with `NEXT_DYNAMIC_NO_SSR_CODE` digest as recoverable:
// https://github.com/vercel/next.js/blob/bef716ad031591bdf94058aaf4b8d842e75900b5/packages/next/src/shared/lib/lazy-dynamic/bailout-to-csr.ts#L2
(error as any).digest = nextjsDigest;

(error as any).recoverableError = "NO_SSR";

return error;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Refactor Error Handling for SSR Compatibility

The noSSRError function is designed to handle errors specifically for server-side rendering scenarios by manipulating the Error.stackTraceLimit. This approach is clever as it reduces the performance overhead of error handling by limiting the stack trace. However, this might obscure useful debugging information in some cases.

  • Pros: Reduces overhead by limiting the stack trace.
  • Cons: Potentially loses valuable debugging information.

Consider providing a configuration option to toggle this behavior based on the environment or the severity of the error, allowing developers more control over error reporting.

export type Deserializer<T> = (value: string) => T;

// This type utility is only used for workaround https://github.com/microsoft/TypeScript/issues/37663
const isFunction = (x: unknown): x is Function => typeof x === "function";
Copy link
Contributor

Choose a reason for hiding this comment

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

Type Definition Issue: Avoid Using 'Function' as a Type

The use of Function as a type for the isFunction utility (line 392) is flagged by static analysis tools. Using Function can lead to maintenance issues and bugs because it is too generic.

  • Pros: Quick and easy way to check for function types.
  • Cons: Lacks specificity, which can lead to bugs if non-function values that are callable (like classes) are passed.

Consider replacing Function with a more specific function type definition that includes the expected arguments and return type, enhancing type safety and clarity.

- const isFunction = (x: unknown): x is Function => typeof x === 'function';
+ const isFunction = (x: unknown): x is (...args: any[]) => any => typeof x === 'function';
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isFunction = (x: unknown): x is Function => typeof x === "function";
const isFunction = (x: unknown): x is (...args: any[]) => any => typeof x === "function";
Tools
Biome

[error] 392-392: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)

@Dogtiti
Copy link
Member

Dogtiti commented Sep 9, 2024

#5386

@Dogtiti Dogtiti closed this Sep 9, 2024
@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


#5386

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants