solidjs / solid-router

A universal router for Solid inspired by Ember and React Router
MIT License
1.13k stars 143 forks source link

flaky cache in CatchAll Route after hydration #464

Closed katywings closed 4 weeks ago

katywings commented 1 month ago

Describe the bug

When an existing createAsync call gets updated because of navigation, e.g. if its part of a CatchAll route, there is a somewhat random chance (probably based on timing) that the cache will return the results from the previous call even if the parameters differ. The example below makes it hopefully more clear 😅, you navigate to /about, but for some reason the cache function sometimes just returns /.

Your Example Website or App

https://stackblitz.com/edit/github-xgtjzp?file=src%2Fcomponents%2FTest.tsx

Steps to Reproduce the Bug or Issue

  1. Implement a CatchAll Route
  2. Add multiple links with urls targeting the CatchAll route
  3. Implement a data function with cache, use server and 1 parameter, that just returns the parameter
  4. Add a createAsync effect that calls the data function with e.g. location.pathname, output the result in the jsx
  5. Reload the browser tab, click on a link
  6. Repeat step 5. multiple times
  7. Notice how the printed pathname sometimes differs from the actual path

Expected behavior

The cached function should always run with the newest arguments after hydration. For the example that means: when I navigate to /about I expect the cache function to be consistently called with /about

Screenshots or Videos

https://github.com/user-attachments/assets/62c15667-eb17-4717-bb80-0fe4d296a8a5

Platform

Additional context

Workaround: In the createAsync call, during the first rerun after hydration, run revalidate on the cache

katywings commented 1 month ago

Further discussion about this issue: https://discord.com/channels/722131463138705510/910635844119982080/1267045977760469124

We noticed that the bug can even occur without createAsync!

ryansolid commented 1 month ago

Yeah the issue is with lazy components and interrupted hydration. It thinks it is still hydrating the initial page load and it loads the data originally fetched from the server instead of refetching.