robisim74/qwik-speak

[Bug report] Components being wrongly called

Closed this issue · 4 comments

Issue description

When using qwik-speak, if we declare a routeLoader$ in the layout.txt file and re-use it across multiple routes, if we navigate through out some pages, both the from and the next component is called.

For example, if we navigate from "Home" to "Page", both the "Home" and "Page" components are called.

This appears to only happen when using qwik-speak and only if routeLoader$ is declared in the layouts.txt. If we declare the routeLoader$ in each route, then the problem does not happen.

I took the opportunity to create a minimal reproduction branch with this problem (currently rebased with master): https://github.com/nelsonprsousa/qwik-speak/tree/min-rep-multiple-comp-calls

Also, please note that, based on my research:

  • this problem does not happen without the use of qwik-speak;
  • as a workaround, we can declare the routeLoader$ in each route instead of layout.txt. The cons is that we need to duplicate the loader declaration in each route.

Steps to reproduce the issue

  1. Clone the repo
  2. Checkout branch min-rep-multiple-comp-calls
  3. yarn && yarn start
  4. Open site and your developer tools
  5. Navigate from Home to Page
  6. Check 2 logs, one from Home component and another one from Page component

What's the expected result?

  • While navigating from Home to Page, only the Page component should be called.

What's the actual result?

  • Both Home and Page components get called while navigating from Home to Page (SPA).

Additional details / screenshot

image

Here's what is happening when we navigate from Home to Page. The Home component is not expected to be called. However, we get both logs, meaning that while navigating from home to page, the home component gets called for some reason.

For reference, here's a discord thread discussion regarding this problem: https://discord.com/channels/842438759945601056/1172197695172128798/1172205507457601626

In the meantime, all new findings regarding this problem should be added here in this issue report.

@nelsonprsousa Thanks for this detailed issue. Thanks to your reproduction I was able to isolate the problem.

You are importing the signal produced by routeLoader$ into the Home and Page components from layout (which is executed at each navigation). The problem is that these components are included in the Speak component, and the Speak component is a Slot component: so it means that everything inside it is isolated, and recalled if something changes (like the routeLoader$ signal).

If you move const pageContextSignal = usePageContextLoader(); in the default component of the pages it works without recalling the component.

I think this is Qwik behavior by design.

The only way this library can avoid this, is to give up the Speak component, and provide a hook for scoped translations, like:

export default component$(() => {
  useSpeak({assets: ['home']});

  return <Home />;
});

Pros:

  • Avoid problems like in this issue
  • No need to create a nested (Home, Page) component for each page

Cons:

  • That wouldn't be a jsx way
  • It would be a breaking change

I will make other evaluations (opinions are welcome), and I will decide what to do.

Thanks for your detailed reply as well.

As a work around I am declaring the routeLoader$ in each individual route (I left the const declared but commented in the minimal reproduction branch).

I am not able to provide useful feedback regarding the solution you suggested since I am yet learning all the Qwik concepts, but I trust your judgment.

Thank you

I'm closing this issue, since from v0.17.0 Speak (slot) component no longer exists, in favor of useSpeak hook.

Greetings