Releases: remix-run/react-router
[email protected]
Patch Changes
-
fix: remove internal router singleton (#9227)
This change removes the internal module-level
routerSingleton
we create and maintain inside our data routers since it was causing a number of headaches for non-simple use cases:- Unit tests are a pain because you need to find a way to reset the singleton in-between tests
- Use use a
_resetModuleScope
singleton for our tests - ...but this isn't exposed to users who may want to do their own tests around our router
- Use use a
- The JSX children
<Route>
objects cause non-intuitive behavior based on idiomatic react expectations- Conditional runtime
<Route>
's won't get picked up - Adding new
<Route>
's during local dev won't get picked up during HMR - Using external state in your elements doesn't work as one might expect (see #9225)
- Conditional runtime
Instead, we are going to lift the singleton out into user-land, so that they create the router singleton and manage it outside the react tree - which is what react 18 is encouraging with
useSyncExternalStore
anyways! This also means that since users create the router - there's no longer any difference in the rendering aspect for memory/browser/hash routers (which only impacts router/history creation) - so we can get rid of those and trim to a simpleRouterProvider
// Before function App() { <DataBrowserRouter> <Route path="/" element={<Layout />}> <Route index element={<Home />}> </Route> <DataBrowserRouter> } // After let router = createBrowserRouter([{ path: "/", element: <Layout />, children: [{ index: true, element: <Home />, }] }]); function App() { return <RouterProvider router={router} /> }
If folks still prefer the JSX notation, they can leverage
createRoutesFromElements
(aliased fromcreateRoutesFromChildren
since they are not "children" in this usage):let routes = createRoutesFromElements( <Route path="/" element={<Layout />}> <Route index element={<Home />}> </Route> ); let router = createBrowserRouter(routes); function App() { return <RouterProvider router={router} /> }
And now they can also hook into HMR correctly for router disposal:
if (import.meta.hot) { import.meta.hot.dispose(() => router.dispose()); }
And finally since
<RouterProvider>
accepts a router, it makes unit testing easer since you can create a fresh router with each test.Removed APIs
<DataMemoryRouter>
<DataBrowserRouter>
<DataHashRouter>
<DataRouterProvider>
<DataRouter>
Modified APIs
createMemoryRouter
/createBrowserRouter
/createHashRouter
used to live in@remix-run/router
to prevent devs from needing to create their ownhistory
. These are now moved toreact-router
/react-router-dom
and handle theRouteObject -> AgnosticRouteObject
conversion.
Added APIs
<RouterProvider>
createRoutesFromElements
(alias ofcreateRoutesFromChildren
)
- Unit tests are a pain because you need to find a way to reset the singleton in-between tests
-
Updated dependencies
[email protected]
Patch Changes
- Updated dependencies
[email protected]
Patch Changes
- fix: rename resetScroll -> preventScrollReset (#9199)
- Updated dependencies
- @remix-run/[email protected]
[email protected]
Patch Changes
-
c3406eb: fix: Rename
<Deferred>
to<Await>
(#9095)- We are no longer replacing the
Promise
onloaderData
with the value/error
when it settles so it's now always aPromise
. - To that end, we changed from
<Deferred value={promise}>
to
<Await resolve={promise}>
for clarity, and it also now supports using
<Await>
with raw promises from anywhere, not only those onloaderData
from a defer() call.- Note that raw promises will not be automatically cancelled on interruptions
so they are not recommended
- Note that raw promises will not be automatically cancelled on interruptions
- The hooks are now
useAsyncValue
/useAsyncError
- We are no longer replacing the
-
Updated dependencies
- @remix-run/[email protected]
[email protected]
Patch Changes
- Updated dependencies
[email protected]
Patch Changes
- Updated dependencies [c3406eb]
[email protected]
Patch Changes
- Updated dependencies
@remix-run/[email protected]
Patch Changes
-
c3406eb: fix: Rename
<Deferred>
to<Await>
(#9095)- We are no longer replacing the
Promise
onloaderData
with the value/error
when it settles so it's now always aPromise
. - To that end, we changed from
<Deferred value={promise}>
to
<Await resolve={promise}>
for clarity, and it also now supports using
<Await>
with raw promises from anywhere, not only those onloaderData
from a defer() call.- Note that raw promises will not be automatically cancelled on interruptions
so they are not recommended
- Note that raw promises will not be automatically cancelled on interruptions
- The hooks are now
useAsyncValue
/useAsyncError
- We are no longer replacing the
[email protected]
Patch Changes
-
feat: Deferred API Updates (#9070)
- Removes
<Suspense>
from inside<Deferred>
, requires users to render their own suspense boundaries - Updates
Deferred
to use a true error boundary to catch render errors as well as data errors - Support array and single promise usages
return deferred([ await critical(), lazy() ])
return deferred(lazy())
- Remove
Deferrable
/ResolvedDeferrable
in favor of rawPromise
's andAwaited
- Remove generics from
useDeferredData
untiluseLoaderData
generic is decided in 6.5
- Removes
-
Updated dependencies
- @remix-run/[email protected]
[email protected]
Patch Changes
- Updated dependencies