-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
05b36bc
commit cba5566
Showing
14 changed files
with
355 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import {Children, isValidElement} from 'react'; | ||
import {Outlet, type RouteObject, type To, useOutletContext} from 'react-router-dom'; | ||
import type {LocationDescriptor} from 'history'; | ||
import * as qs from 'query-string'; | ||
|
||
import {useLocation} from './useLocation'; | ||
import {useParams} from './useParams'; | ||
import useRouter from './useRouter'; | ||
import {useRoutes} from './useRoutes'; | ||
|
||
function isComponent( | ||
element: JSX.Element | ||
): element is React.ReactElement<any, React.NamedExoticComponent<any>> { | ||
return typeof element.type !== 'string'; | ||
} | ||
|
||
/** | ||
* Because some of our vies use cloneElement to inject route props into the | ||
* children views, we need to capture those props and pass them as outlet | ||
* context. The WithReactRouter3Props HoC component will inject the outlet | ||
* context into the view | ||
*/ | ||
function OurOutlet(props: any) { | ||
return <Outlet context={props} />; | ||
} | ||
|
||
/** | ||
* HoC which injects params and a route object that emulate react-router3 | ||
*/ | ||
function withReactRouter3Props(Component: React.ComponentType<any>) { | ||
function WithReactRouter3Props() { | ||
const params = useParams(); | ||
const router = useRouter(); | ||
const routes = useRoutes(); | ||
const location = useLocation(); | ||
const outletContext = useOutletContext<{}>(); | ||
|
||
return ( | ||
<Component | ||
router={router} | ||
routes={routes} | ||
params={params} | ||
location={location} | ||
{...outletContext} | ||
> | ||
<OurOutlet /> | ||
</Component> | ||
); | ||
} | ||
|
||
return WithReactRouter3Props; | ||
} | ||
|
||
function getElement(Component: React.ComponentType | undefined) { | ||
if (!Component) { | ||
return undefined; | ||
} | ||
|
||
const WrappedComponent = withReactRouter3Props(Component); | ||
|
||
return <WrappedComponent />; | ||
} | ||
|
||
/** | ||
* Transforms a react-router 3 style route tree into a valid react-router 6 | ||
* router tree. | ||
*/ | ||
export function buildReactRouter6Routes(tree: JSX.Element) { | ||
const routes: RouteObject[] = []; | ||
|
||
Children.forEach(tree, routeNode => { | ||
if (!isValidElement(routeNode)) { | ||
return; | ||
} | ||
if (!isComponent(routeNode)) { | ||
return; | ||
} | ||
|
||
const isRoute = routeNode.type.displayName === 'Route'; | ||
const isIndexRoute = routeNode.type.displayName === 'IndexRoute'; | ||
|
||
// Elements that are not Route components are likely fragments, just | ||
// traverse into their children in this case. | ||
if (!isRoute && !isIndexRoute) { | ||
routes.push(...buildReactRouter6Routes(routeNode.props.children)); | ||
return; | ||
} | ||
|
||
const {path, component: Component, children} = routeNode.props; | ||
const element = getElement(Component); | ||
|
||
if (isIndexRoute) { | ||
routes.push({path, element, index: true}); | ||
} else { | ||
routes.push({path, element, children: buildReactRouter6Routes(children)}); | ||
} | ||
}); | ||
|
||
return routes; | ||
} | ||
|
||
/** | ||
* Translates a react-router 3 LocationDescriptor to a react-router 6 To. | ||
*/ | ||
export function locationDescriptorToTo(path: LocationDescriptor): To { | ||
if (typeof path === 'string') { | ||
return path; | ||
} | ||
|
||
const to: To = { | ||
pathname: path.pathname, | ||
}; | ||
|
||
if (path.hash) { | ||
to.hash = path.hash; | ||
} | ||
if (path.search) { | ||
to.search = path.search; | ||
} | ||
if (path.query) { | ||
to.search = `?${qs.stringify(path.query)}`; | ||
} | ||
|
||
// XXX(epurkhiser): We ignore the location state param | ||
|
||
return to; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,45 @@ | ||
import {useMemo} from 'react'; | ||
import {useLocation as useReactRouter6Location} from 'react-router-dom'; | ||
import type {Location, Query} from 'history'; | ||
import * as qs from 'query-string'; | ||
|
||
import {USING_REACT_ROUTER_SIX} from 'sentry/constants'; | ||
import {useRouteContext} from 'sentry/utils/useRouteContext'; | ||
|
||
type DefaultQuery<T = string> = { | ||
[key: string]: T | T[] | null | undefined; | ||
}; | ||
|
||
export function useLocation<Q extends Query = DefaultQuery>(): Location<Q> { | ||
const route = useRouteContext(); | ||
return route.location; | ||
if (!USING_REACT_ROUTER_SIX) { | ||
// biome-ignore lint/correctness/useHookAtTopLevel: react-router 6 migration | ||
return useRouteContext().location; | ||
} | ||
|
||
// biome-ignore lint/correctness/useHookAtTopLevel: react-router 6 migration | ||
const {pathname, search, hash, state, key} = useReactRouter6Location(); | ||
|
||
// biome-ignore lint/correctness/useHookAtTopLevel: react-router 6 migration | ||
const query = useMemo(() => qs.parse(search) as Q, [search]); | ||
|
||
// biome-ignore lint/correctness/useHookAtTopLevel: react-router 6 migration | ||
const location = useMemo( | ||
() => | ||
({ | ||
pathname: pathname, | ||
search: search, | ||
query, | ||
hash: hash, | ||
state, | ||
key, | ||
|
||
// XXX(epurkhiser): It would be possible to extract this from the | ||
// react-router 6 browserHistory object. But beecause of how we're | ||
// shimming it it's a little hard, so for now just mock | ||
action: 'POP', | ||
}) satisfies Location<Q>, | ||
[hash, key, pathname, query, search, state] | ||
); | ||
|
||
return location; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.