#'<A> and 'use' router primitives can be only used inside a Route' as a result of props laziness

8 messages · Page 1 of 1 (latest)

neat tapir
#

Hi, I've been confused by this error a bit whilst writing my application and I have just constructed a minimal reproducible example and now it clicks. But I'd be interested in knowing what I can do to avoid this problem in the future:

import { RouteSectionProps, useLocation, useParams } from "@solidjs/router";
import { Component } from "solid-js";

export const TestPage: Component<RouteSectionProps<unknown>> = (props) => {
  return (
    <b>
      This is a test page! <SubComponent path={useLocation().pathname} />
    </b>
  );
};

const SubComponent: Component<{ path: string }> = (props) => (
  <button
    type="button"
    style="border: 1px solid blue; padding: 3em;"
    onClick={() => console.log(props.path)}
  >
    Clicky!
  </button>
);

Clicking the button produces the error (whilst evaluating props.path): '<A> and 'use' router primitives can be only used inside a Route.'

My understanding of the problem here: presumably the event handler onClick runs outside of a tracking scope, so useLocation(), which is invoked lazily because of props.path actually just being a property getter, is not run with the router in scope and so it doesn't know what to return.

Although I can usually figure out how to eagerly evaluate props.path if I put my mind to it, I am struggling to fix this in a way that ensures I don't keep making this mistake again and again, any ideas?

Thanks

deep cove
#

Your understanding is correct, the way to make it work is to hoist the useLocation call into the component body, then just do .pathname in the prop

#

No need to worry about eagerly evaluating props.path

neat tapir
#

So you're correct that this works:

export const TestPage: Component<RouteSectionProps<unknown>> = (props) => {
  const location = useLocation();
  return (
    <b>
      This is a test page! <SubComponent path={location.pathname} />
    </b>
  );
};

Will I not lose reactivity (from changes in the path) from this?

#

useLocation says 'Retrieves reactive location object useful for getting things like pathname.' so maybe it's still a magicly-reactive thing

#

ah woot, it is all fine

#

I changed to this for a test:

import { RouteSectionProps, useLocation, useParams } from "@solidjs/router";
import { Component } from "solid-js";

export const TestPage: Component<RouteSectionProps<unknown>> = (props) => {
  const location = useLocation();
  console.log("evaled");
  return (
    <b>
      This is a test page! <SubComponent path={location.pathname} />
      <a href="/test/path1">(1)</a>
      <a href="/test/path2">(2)</a>
    </b>
  );
};

const SubComponent: Component<{ path: string }> = (props) => (
  <button
    type="button"
    style="border: 1px solid blue; padding: 3em;"
    onClick={() => console.log(props.path)}
  >
    Clicky!
  </button>
);

Using the links to navigate to different paths (which both route to the same component fwiw), I don't see the evaled log line (so the component is not being re-evaluated) yet the correct path is logged

#

Thank you very much! 😄