From 0b59aac33b7d9fbe0a43610ade0e8199c4d4b61b Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Wed, 28 Feb 2024 11:20:34 -0500 Subject: [PATCH] Ensure remix react re-exports everything from react-router-dom (#8929) --- .changeset/small-berries-rush.md | 5 ++ .../remix-react/__tests__/exports-test.tsx | 65 +++++++++++++++++++ packages/remix-react/index.tsx | 9 +++ 3 files changed, 79 insertions(+) create mode 100644 .changeset/small-berries-rush.md create mode 100644 packages/remix-react/__tests__/exports-test.tsx diff --git a/.changeset/small-berries-rush.md b/.changeset/small-berries-rush.md new file mode 100644 index 00000000000..533893e9c77 --- /dev/null +++ b/.changeset/small-berries-rush.md @@ -0,0 +1,5 @@ +--- +"@remix-run/react": patch +--- + +Ensure `@remix-run/react` re-exports everything from `react-router-dom` for SPA mode diff --git a/packages/remix-react/__tests__/exports-test.tsx b/packages/remix-react/__tests__/exports-test.tsx new file mode 100644 index 00000000000..ae912a87fb5 --- /dev/null +++ b/packages/remix-react/__tests__/exports-test.tsx @@ -0,0 +1,65 @@ +import * as ReactRouterDOM from "react-router-dom"; +import * as RemixReact from "@remix-run/react"; + +let nonReExportedKeys = new Set([ + // Internal error used by Remix + "AbortedDeferredError", + // Remix manages the router for you, so we don't re-export these + "BrowserRouter", + "HashRouter", + "MemoryRouter", + "Router", + "RouterProvider", + "createBrowserRouter", + "createHashRouter", + "createMemoryRouter", + // Don't re-export unsafe APIs + "unstable_HistoryRouter", + "UNSAFE_DataRouterContext", + "UNSAFE_DataRouterStateContext", + "UNSAFE_FetchersContext", + "UNSAFE_LocationContext", + "UNSAFE_NavigationContext", + "UNSAFE_RouteContext", + "UNSAFE_ViewTransitionContext", + "UNSAFE_useRouteId", + "UNSAFE_useScrollRestoration", +]); + +// Eventually we should im to get these all aligned so we can +// `export * from react-router-dom`. Most of the differences are Remix-specific +// type safety, plus Link/NavLink have wrappers to support prefetching +let modifiedExports = new Set([ + "Await", // types + "Link", // remix-specific prefetching loigc + "NavLink", // remix-specific prefetching loigc + "ScrollRestoration", // remix-specific SSR restoration logic + "defer", // types + "json", // types + "redirect", // types + "redirectDocument", // types + "useActionData", // types + "useFetcher", // types + "useLoaderData", // types + "useMatches", // types + "useRouteLoaderData", // types +]); + +describe("re-exports from react-router-dom", () => { + for (let key in ReactRouterDOM) { + if (nonReExportedKeys.has(key)) { + it(`does not re-export ${key} from react-router`, () => { + expect(RemixReact[key] === undefined).toBe(true); + }); + } else if (modifiedExports.has(key)) { + it(`re-exports a different version of ${key}`, () => { + expect(RemixReact[key] !== undefined).toBe(true); + expect(RemixReact[key] !== ReactRouterDOM[key]).toBe(true); + }); + } else { + it(`re-exports ${key} from react-router`, () => { + expect(RemixReact[key] === ReactRouterDOM[key]).toBe(true); + }); + } + } +}); diff --git a/packages/remix-react/index.tsx b/packages/remix-react/index.tsx index 7d2102889f6..b4336440722 100644 --- a/packages/remix-react/index.tsx +++ b/packages/remix-react/index.tsx @@ -19,12 +19,18 @@ export type { } from "react-router-dom"; export { createPath, + createRoutesFromChildren, + createRoutesFromElements, + createSearchParams, generatePath, matchPath, matchRoutes, parsePath, + renderMatches, resolvePath, Form, + Navigate, + NavigationType, Outlet, Route, Routes, @@ -35,6 +41,8 @@ export { useFetchers, useFormAction, useHref, + useInRouterContext, + useLinkClickHandler, useLocation, useMatch, useNavigate, @@ -46,6 +54,7 @@ export { useResolvedPath, useRevalidator, useRouteError, + useRoutes, useSearchParams, useSubmit, useBlocker,