kjh
kjh

Reputation: 53

SolidJS Uncaught Error: <A> and 'use' router primitives can be only used inside a Route

I got some issues with my solidjs (Vanilla JS) code. I try to build a small three page Website, just to print out some Information. I use vitejs, solidjs and tailwindcss. I was able to build the relevant sections, some reactivity and my desired three sites. All on its own works well. The thing I can't manage is Routing.

My index.html looks for the App.jsx. Within the App.jsx I do the relevant imports, load and display my components and render everything. It looks something like this:

import { render } from "solid-js/web";
import { Router, Route } from "@solidjs/router";
import "./app.css";
const root = document.getElementById("root");
import Header from "./components/Header";
import Footer from "./components/Footer";
import Home from "./pages/Home";
import Impressum from "./pages/Impressum";
import NotFound from "./pages/404";

function App() {
  return (
    <>
      <Header />
      <Router>
        <Route path="/" component={Home} />
        <Route path="/impressum" component={Impressum} />
        <Route path="*404" component={NotFound} />
      </Router>
      <Footer />
    </>
  );
}

render(() => <App />, root);

In the Header component is a navigation bar with links. I also import A from solidjs/router in it. It looks something like this (I don't show the styles and other functionality which works fine):

import { createSignal, onCleanup, onMount, createEffect } from "solid-js";
import { A } from "@solidjs/router";
//import LinkList from "./LinkList";
import { Collapse, Dropdown, Ripple, initTWE } from "tw-elements";
import logo from "../assets/logo.svg";

[...]

<nav>
 <ul>
  <li><A href ="/">Home</A></li>
  <li><A href ="/impressum">Impressum</A></li>
 </ul>
</nav>

Running the dev server gives me the following error:

Uncaught Error: and 'use' router primitives can be only used inside a Route.

I tried different wrappers, asked chatGPT and have been on Google for hours. I can't figure out what is wrong. I'm not very long into programming. Also English isn't my native language...

Upvotes: 4

Views: 1656

Answers (3)

Erik Popsky
Erik Popsky

Reputation: 11

I had the same problem and i fixed it on my project , follow my example and it will work. If u have some problem , i am sorry , i am begginer.

function App() {
  return (
    <Router
      root={(props) => (
        <>
          <HeaderComponent />
          <div class="main-content">{props.children}</div>
        </>
      )}
    >
      <Route path="/" component={HomePage} />
      <Route path="/aboutus" component={AboutUsPage} />
      <Route path="/products" component={ProductPage} />
      <Route path="/product/:id" component={ProductDetailsPage} />
      <Route path="/cart" component={CartPage} />
      <FooterComponent />
    </Router>
  );
}

export default App;

Upvotes: 1

Marco Klein
Marco Klein

Reputation: 699

Instead of manually wrapping your components with a layout component, solidjs router can do it for you.

For example, if you need to globally attach a router event, like useBeforeLeave, you can supply your router with a root component:

<Router root={Layout}>{routes}</Router>
import { RouteSectionProps, useBeforeLeave } from '@solidjs/router';

export function Layout(props: RouteSectionProps) {
  useBeforeLeave(e => console.log(e));

  return <>{props.children}</>;
}

The router will then render the Layout component around each and every route inside automatically.

Upvotes: 0

snnsnn
snnsnn

Reputation: 13698

As the warning states, you can use an A element or other elements that rely on the router API under a Route component.

The problem is that you have an A component directly under the Router component through the Header component but it should be wrapped by a Route first. So, you need to move those links under a component that is used for a path.

The idea is that the navigation items are always associated with a route. It is like links can exist inside a page.

import { A, Route, Router } from '@solidjs/router';
import { render } from 'solid-js/web';

function App() {  
  const Home = () => (
    <div>
      <ul>
        <li><A href='/blog'>Blog</A></li>
        <li><A href='/users'>Users</A></li>
      </ul>
      <div>This is home page!</div>
    </div>
  );

  const Users = () => <div>Users</div>;
  const Blog = () => <div>Blog</div>;
  const NotFound = () => <div>NotFound</div>;

  return (
    <Router>
      <Route path="/" component={Home} />
      <Route path="/users" component={Users} />
      <Route path="/blog" component={Blog} />
      <Route path="*404" component={NotFound} />
    </Router>
  );
}

render(() => <App />, document.body);

Alternatively, you can use a layout component:

const Layout: Component<{ children: JSX.Element }> = (props) => {
  return (
    <div>
      <ul>
        <li><A href='/'>Home</A></li>
        <li><A href='/blog'>Blog</A></li>
        <li><A href='/users'>Users</A></li>
      </ul>
      {props.children}
    </div>
  );
};

const Home: Component<{}> = () => <Layout><div>This is Home page!</div></Layout>

The router above is intended to be used with server rendered app. If you are going to use it for SPA, make sure you use the hash mode router:

import { HashRouter } from "@solidjs/router";

Otherwise you will have page not found error when you refresh the page when you are on a sub-route.

PS: Solid Router has undergone some major updates, I believe for better SSR support, this is one of the changes that is brought about the latest update.

Upvotes: 1

Related Questions