#useLocation() may be used only in the context of a Router component.

1 messages · Page 1 of 1 (latest)

vague linden
#

The following ues of the NavLink component is throw an error:

<nav className="-mb-px flex space-x-8" aria-label="Tabs">
            {tabs.map((tab) => (
              <NavLink
                key={tab.name}
                to={tab.to}
                prefetch="render"
                className={classNames(
                  tab?.current
                    ? "border-indigo-500 text-indigo-600"
                    : "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300",
                  "whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
                )}
              >
                {tab.name}
              </NavLink>
            ))}
          </nav>
lavish lily
#

you should render NavLink inside a Router component

#

like BrowserRouter or MemoryRouter

vague linden
#

was there an update recently?

#

where can I see the docs for this?

lavish lily
#

that should have always be the case

#

ohh I just saw you're using Remix, not just React Router

#

then it should work

#

because all components in Remix are inside a Router component unless you render something along RemixBrowser and RemixServer in the entry files

vague linden
#

this is on a component rendered by a parent route component with <Outlet>

lavish lily
#

try to create a reproduction repo and submit open an issue because this looks like a bug

vague linden
#

ok

wet patrol
#

Hi, I am suffering the same problem when updated to react 18 and last remix version

#

Did you solve the problem?

#

I updated the entry.client and entry.server files to be in line with the indie stack version

#
import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";

const hydrate = () => {
  startTransition(() => {
    hydrateRoot(
      document,
      <StrictMode>
        <RemixBrowser />
      </StrictMode>
    );
  });
};

if (window.requestIdleCallback) {
  window.requestIdleCallback(hydrate);
} else {
  // Safari doesn't support requestIdleCallback
  // https://caniuse.com/requestidlecallback
  window.setTimeout(hydrate, 1);
}

entry.server

import { PassThrough } from "stream";
import type { EntryContext } from "@remix-run/node";
import { Response } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
import isbot from "isbot";
import { renderToPipeableStream } from "react-dom/server";

const ABORT_DELAY = 5000;

export default function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  const callbackName = isbot(request.headers.get("user-agent"))
    ? "onAllReady"
    : "onShellReady";

  return new Promise((resolve, reject) => {
    let didError = false;

    const { pipe, abort } = renderToPipeableStream(
      <RemixServer context={remixContext} url={request.url} />,
      {
        [callbackName]: () => {
          const body = new PassThrough();

          responseHeaders.set("Content-Type", "text/html");

          resolve(
            new Response(body, {
              headers: responseHeaders,
              status: didError ? 500 : responseStatusCode,
            })
          );

          pipe(body);
        },
        onShellError: (err: unknown) => {
          reject(err);
        },
        onError: (error: unknown) => {
          didError = true;

          console.error(error);
        },
      }
    );

    setTimeout(abort, ABORT_DELAY);
  });
}