question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[DISCUSSION] Exploring component-based routing

See original GitHub issue

Is your feature request related to a problem?

Modern frameworks tend to provide, built-in or on-side, routing solution. Qwik doesn’t.

Describe the solution you’d like

Implement a solution to allow using different components as views to replicate SPA routing behaviour.

Describe alternatives you’ve considered

HTML routing. However, for modern applications this is considered not-so-welcome experience.

Additional context

I’ve run my attempt at creating a routable app. And, this is what I got to:

import { useStore, component$, Host, Component } from "@builder.io/qwik";
import { Logo } from "../logo/logo";

import "./global.css";

export const HomePage = component$(({ greeting }: { greeting: string }) => {
  return <h1>Home Page {greeting}</h1>;
});
export const AboutPage = component$(({ greeting }: { greeting: string }) => {
  return <h1>About Page {greeting}</h1>;
});

export const ROUTES: Record<string, Component<any>> = {
  "/": HomePage,
  "/about": AboutPage,
};

export const App = component$(() => {
  const state = useStore({
    greeting: "world!",
    route: "/",
  });
  return (
    <Host class="my-app p-20">
      <Logo class="mb-10" />

      <h1 class="text-3xl mb-2">Congratulations Qwik is working!</h1>

      <a
        href="/#/about"
        onClick$={() => {
          state.route = "/about";
        }}
      >
        About
      </a>

      <li>
        Try interacting with this component by changing{" "}
        <input
          value={state.greeting}
          class="border-2 border-solid border-blue-500"
          placeholder="Write some text"
          onInput$={(event) => {
            const input = event.target as HTMLInputElement;
            state.greeting = input.value;
          }}
        ></input>
        .
      </li>
      <li>
      <li>
        Observe that the binding changes: <code>Hello {state.greeting}!</code>
      </li>

      {ROUTES[state.route]({
        greeting: state.greeting,
      })}
    </Host>
  );
});

The above example, brings routing which replicates something like Angular, where we define a map of routes, which Angular uses to replace a router-outlet with the appropriate component matching the route. Now, only if I figured my way through the following attempt:

  const state = useStore(() => {
    const route = global.window.location.hash.replace("#", "");
    return {
      greeting: "world!",
      route,
    };
  });

I would also be able to get the route from current document location.

Overall, does this get inline with how Qwik team is looking at routing? Does the team already have some other approach that can be shared with the community so might we collectively can shape it?

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:18 (8 by maintainers)

github_iconTop GitHub Comments

3reactions
nnelgxorzcommented, Jul 30, 2022

Oh, the really crazy part is you only get SPA behavior when you use a Link component. All your regular links are still MPA. You have both routing options available at the same time and can choose which one is best whenever you want. 👀

3reactions
IgnusGcommented, Jun 11, 2022

Thanks for the links, @nnelgxorz, and thanks for your attempt to work with me on this. I really appreciate it.

I’m sure I need to dig more into this. I’m considering manipulating internals of Qwik to see whether adding preventDefault to the callable created by Qwik would make a difference. This IMO is better approach that using proxy elements acting as links because this anti-semantic approach definitely is going to break in some way, and I’m hoping to reach a point where I can have client-side routing, that is in consistent with regular routing.

@mahmoudajawad You could use something like this inline (note the onclick which binds to the native dom’s click handler - this feels technically “illegal” but hey, JSX police ain’t watching):

router = useStore({ route: "/" });

<a 
  onclick={(e) => e.preventDefault()}
  onClick$={() => router.route = "/about"}
  href="/about"
>
  My Link
</a>
);

Or for a more type safe and less hacky solution using a wrapper component:

export const Link = component$(
  ({ onClickQrl, href }: { onClickQrl: QRL<() => void>; href: string }) => {
    const anchor = useRef<HTMLAnchorElement>();

    useClientEffect$(() => {
      anchor.current?.addEventListener("click", (event) => {
        event.preventDefault();
      });
    });

    return (
      <a onClickQrl={onClickQrl} href={href} ref={anchor}>
        <Slot />
      </a>
    );
  },
);
Read more comments on GitHub >

github_iconTop Results From Across the Web

UI5 – Component Based Routing - SAP Blogs
UI5 – Component Based Routing · components are declared in the sap.ui5.componentUsages section · routes have a prefix property assigned · targets ...
Read more >
How to enable routing and navigation between component ...
The task is to enable routing between angular components by making their routes when a user clicks the link, it will be navigated...
Read more >
Using a Switch Component in React Router
Routing in React can be a little difficult for those who are new to React. ... the Home , Login , and Explore...
Read more >
Angular Router Series: Secondary Outlets Primer - InDepth.Dev
In this short article, we're going to explore secondary outlets (sometimes called named router outlets), and see the role they play in routing....
Read more >
Exploring SvelteKit, the newest Svelte-based framework
You'll also notice the $layout.svelte component inside routes/ ; this can display and style things that are persistent across different routes, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found