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

Wait for previous navigation done before navigating to param with new updated value #73

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

TravelingTice
Copy link
Contributor

@TravelingTice TravelingTice commented Mar 4, 2024

This PR tries to solve the bug explained in issue: #71

The problem is that navigation is "overwritten" when there is another store update right after the previous one (for example when a component mounts that has a bind:value to a new store that uses queryParam.

The way I managed to solve it is by subscribing to the navigating store provided by Sveltekit. This way you can know if it's currently navigating to a different url or page. Then when this is the case in the _set action, I just subscribe to the same store again there to wait until navigating is back to false, and then perform the same _set action. This solved it for me!

Let me know if this is a viable solution. I'm no expert in Sveltekit's internals so I have no idea if this is a proper/safe fix with or without any side effects. I'm just creating a simple app that doesn't have any server routing. But this did solve it in my case.

Also I'm not sure if the same bug appears in the other provided store builder queryParameters. I'm not using that one but looking at the code it looks very similar, so maybe a similar fix will work there. But not sure. Let me know if this is any good 😅

Summary by CodeRabbit

  • Bug Fixes
    • Improved navigation responsiveness by ensuring updates only occur when navigation is not in progress.
  • New Features
    • Enhanced queryParam function to handle navigation states effectively.
    • Introduced a subscription mechanism to manage subscriptions and navigation events.
    • Added functionality to update param2 when param1 changes using query parameters.
  • Tests
    • Added a test case to verify correct URL search parameter updates when changing multiple parameters.

Copy link

changeset-bot bot commented Mar 4, 2024

⚠️ No Changeset found

Latest commit: 3d6e5fe

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

coderabbitai bot commented Mar 4, 2024

Walkthrough

The recent update enhances the queryParam function in a SvelteKit application to handle navigation states effectively. It now prevents updates during navigation, ensuring data consistency. A new subscription mechanism has been introduced to manage subscriptions and navigation events efficiently, providing a smoother user experience.

Changes

Files Change Summary
src/lib/sveltekit-search-params.ts Enhanced queryParam with navigation status check to prevent updates during navigation.
playground/src/routes/paramOnNavigateBug/+page.svelte Added functionality to update param2 based on changes in param1 using query parameters.

Related issues

  • Crashes with enabled prerendering #67
    • This PR addresses the bug where using queryParam in a SvelteKit project with prerendering crashes the build due to url.searchParams access issue. The enhancement in sveltekit-search-params.ts should resolve this bug by handling navigation states effectively.

Poem

🐇✨
In the code's vast, green field,
A clever rabbit hopped and kneeled.
"Before we leap, let's look," it said,
Ensure no path we tread is tread."
With wisdom and a tiny grin,
It fixed the flow, so smooth within.
🚀🌌

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-tests 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 tests 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 tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

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 as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • 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/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

Copy link

netlify bot commented Mar 4, 2024

Deploy Preview for sveltekit-search-params ready!

Name Link
🔨 Latest commit 3d6e5fe
🔍 Latest deploy log https://app.netlify.com/sites/sveltekit-search-params/deploys/65fbd8af5bca2400083c832f
😎 Deploy Preview https://deploy-preview-73--sveltekit-search-params.netlify.app
📱 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.

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.

Review Status

Actionable comments generated: 1

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 3f21aab and 1c99087.
Files selected for processing (1)
  • src/lib/sveltekit-search-params.ts (2 hunks)
Additional comments: 1
src/lib/sveltekit-search-params.ts (1)
  • 341-349: The logic to delay the _set function execution until navigation is complete is a smart approach to solving the issue at hand. However, there are a few considerations:
  • Recursion: The recursive call to _set within the subscription callback (line 344) is an interesting solution but could potentially lead to issues if the navigation status changes are frequent or if there are multiple rapid successive navigations. It's important to ensure that this does not create an infinite loop or excessive stack depth under certain conditions.
  • Unsubscription: The subscription to the navigating store within the _set function is correctly managed with an unsubscribe call (line 345). This is good practice and helps prevent memory leaks.

Consider adding safeguards to prevent potential issues with recursion and ensure that the solution scales well with frequent or complex navigation patterns.

Comment on lines 330 to 335
let isNavigating = false;
if (browser) {
navigating.subscribe((nav) => {
isNavigating = nav?.type === 'goto';
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Tip

Codebase Verification

The investigation into the usage of navigating.subscribe within src/lib/sveltekit-search-params.ts reveals that there is indeed an explicit unsubscription mechanism in place within the _set function, which addresses the concern about potential memory leaks by ensuring proper cleanup. This demonstrates a level of care in managing subscriptions to the navigating store. However, the initial concern regarding the potential performance impact of multiple subscriptions, especially in applications with frequent navigation updates, remains valid. It's recommended to continue monitoring and optimizing subscription management to the navigating store to mitigate any potential performance issues.

Analysis chain

The implementation of subscribing to the navigating store to set isNavigating based on the navigation type is a clever way to handle the issue of rapid successive navigation commands. However, there are a couple of points to consider:

  • Performance: Subscribing to the navigating store every time the queryParam function is called could potentially lead to performance issues, especially in applications with frequent navigation updates. It might be more efficient to manage the subscription at a higher level or use a shared state to track navigation status.
  • Unsubscription: It's good practice to unsubscribe from Svelte stores when the subscription is no longer needed to prevent memory leaks. In this case, the subscription created on line 332 does not seem to be explicitly unsubscribed from. While Svelte might handle this automatically in some scenarios, explicitly managing subscriptions is generally safer.

Consider optimizing the subscription management to the navigating store to improve performance and ensure proper cleanup.


Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify if there's a shared navigation status management implemented elsewhere in the codebase
rg "navigating.subscribe" --type ts

Length of output: 194



Script:

#!/bin/bash
# Extract more details about the second occurrence of navigating.subscribe and its surrounding code
rg -C 5 "const unsubscribe = navigating.subscribe" --type ts

Length of output: 785

@paoloricciuti
Copy link
Owner

Hey thanks for the contribution...i think this could be a good idea but i'm a little worried about not unsubscribing from navigating. I think a better approach would be to subscribe to navigating inside each builder function (basically queryParam and queryParameters), store the unsubscribe in a variable so that you can call it togheter with the unsubscribe from the derived store.

If you need guidance on this feel free to hit me up.

Also it would be wonderful if you could write a failing test that pass after the fix, again if you need guidance on this i can help you 😄

@TravelingTice
Copy link
Contributor Author

TravelingTice commented Mar 4, 2024

Hey! Thanks and glad you like the suggested approach :) Yes subscribing globally feels a bit tricky indeed, will try to fix that. Also the test sounds good indeed! Haven't explored testing yet here so will do so when I have a bit more time on my hands. Will let you know if I run into any trouble

Also do you know why Netlify action is failing? Seems to be having trouble installing dependencies for some reason..

@paoloricciuti
Copy link
Owner

Hey! Thanks and glad you like the suggested approach :) Yes subscribing globally feels a bit tricky indeed, will try to fix that. Also the test sounds good indeed! Haven't explored testing yet here so will do so when I have a bit more time on my hands. Will let you know if I run into any trouble

Also do you know why Netlify action is failing? Seems to be having trouble installing dependencies for some reason..

I think they are failing because you are not in my organization but should not be a problem at all. Let me know if you need any help with testing or in general to fix this.

@paoloricciuti
Copy link
Owner

Actually is failing because I've updated sveltekit and netlify project is still running on node 16...will fix that

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.

Review Status

Actionable comments generated: 1

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 1c99087 and 4c7d474.
Files selected for processing (3)
  • playground/src/routes/paramOnNavigateBug/+page.svelte (1 hunks)
  • src/lib/sveltekit-search-params.ts (5 hunks)
  • tests/index.test.ts (1 hunks)
Additional comments: 4
playground/src/routes/paramOnNavigateBug/+page.svelte (1)
  • 12-15: The button's click handler correctly updates param1, demonstrating proper use of Svelte's reactive store assignments.
src/lib/sveltekit-search-params.ts (2)
  • 338-346: The logic to delay updates during navigation by checking isNavigating is a good approach. However, consider optimizing the subscription management to the navigating store to prevent potential performance issues and ensure proper cleanup. Specifically, ensure that subscriptions are unsubscribed when no longer needed.
  • 440-451: Ensure consistent application of subscription management practices throughout the file. Specifically, apply an unsubscription mechanism for all subscriptions to the navigating store to prevent memory leaks and optimize performance.
tests/index.test.ts (1)
  • 136-154: The test case correctly verifies that changing multiple parameters updates the URL as expected. To further improve the test's robustness, consider adding assertions for the initial state of param1 and param2 before the button click. This ensures that the test covers the scenario where parameters are updated from their initial values.

playground/src/routes/paramOnNavigateBug/+page.svelte Outdated Show resolved Hide resolved
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.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 4c7d474 and 3d6e5fe.
Files selected for processing (1)
  • playground/src/routes/paramOnNavigateBug/+page.svelte (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • playground/src/routes/paramOnNavigateBug/+page.svelte

@TravelingTice
Copy link
Contributor Author

Hmm went a bit further with this one and it looks like the current solution won't solve it in the case described in #71. The problem is that in my app, the new query param would mount after the other one was updated. But in this case, 1 param directly depends on and is subscribed to the updates of the other param. Making updating really fast. Too fast for navigating to even start working. See some debug logs locally:

image

In the playground test case I added, navigating gets triggered for both param updates, before navigating state is updated

image
In my app, subscribing happens after navigating has started, meaning current fix will be working

I'm pretty deep in it but unfortunately not sure how to solve this one 😓

@paoloricciuti
Copy link
Owner

Hmm went a bit further with this one and it looks like the current solution won't solve it in the case described in #71. The problem is that in my app, the new query param would mount after the other one was updated. But in this case, 1 param directly depends on and is subscribed to the updates of the other param. Making updating really fast. Too fast for navigating to even start working. See some debug logs locally:

image

In the playground test case I added, navigating gets triggered for both param updates, before navigating state is updated

image In my app, subscribing happens after navigating has started, meaning current fix will be working

I'm pretty deep in it but unfortunately not sure how to solve this one 😓

Mmm interesting...i will try to investigate this a bit myself. This is definitely a bit of an edge case but it's definitely something worth investing into fixing.

@paoloricciuti
Copy link
Owner

Ok i've investigating this a bit and yeah there's no way to wait for the navigation without disrupting the rest of the flow and there's no way to know that you want to do that just by looking at the assignment. Maybe the best option would be another api. I will try as soon as i have time.

@TravelingTice
Copy link
Contributor Author

Yeah it's definitely a very tricky one! I wish I had some more time to look into it as well.. hope you can find a nice solution..

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.

2 participants