kibana/packages/shared-ux/router/impl/router.tsx
Rachel Shen 50a4fc4916
[Shared UX] Adoption of Shared UX Route component (#150357)
## Summary

This PR removes all imports of Route from react-router-dom and
'@kbn/kibana-react-plugin/public' and instead imports Route from
@kbn/shared-ux-router.

### Context
Based on
https://github.com/elastic/kibana/issues/132629#issue-1243243678 This PR
executes steps 2 - 4:

> 2. To make the transition easier, we want to re-export other
react-router-dom exports alongside the modified' Route'.
> 3. Solutions should start using that Route component in place of the
one from react-router-dom. I.e. replace all occurrences of import { ...
} from 'react-router-dom' with import { ... } from
'@kbn/shared-ux-router'.
> 4. All manual calls to useExecutionContext are not needed anymore and
should be removed.

### Future PR

Looks like this might be getting worked on in:
https://github.com/elastic/kibana/pull/145863 (thanks!)

> Introduce an ESlint rule that ensures that react-router-dom is not
used directly in Kibana and that imports go through the new
@kbn/shared-ux-router package.

This is tangentially accomplished through
https://github.com/elastic/kibana/pull/150340 but only addresses using
Route through @kbn/kibana-react-plugin/public'


### Checklist

Delete any items that are not applicable to this PR.

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Tiago Costa <tiagoffcc@hotmail.com>
2023-02-14 19:25:04 +00:00

79 lines
2.3 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React, { useMemo } from 'react';
import {
// eslint-disable-next-line no-restricted-imports
Route as ReactRouterRoute,
RouteComponentProps,
RouteProps,
useRouteMatch,
} from 'react-router-dom';
import { useKibanaSharedUX } from './services';
import { useSharedUXExecutionContext } from './use_execution_context';
/**
* This is a wrapper around the react-router-dom Route component that inserts
* MatchPropagator in every application route. It helps track all route changes
* and send them to the execution context, later used to enrich APM
* 'route-change' transactions.
*/
export const Route = ({ children, component: Component, render, ...rest }: RouteProps) => {
const component = useMemo(() => {
if (!Component) {
return undefined;
}
return (props: RouteComponentProps) => (
<>
<MatchPropagator />
<Component {...props} />
</>
);
}, [Component]);
if (component) {
return <ReactRouterRoute {...rest} component={component} />;
}
if (render || typeof children === 'function') {
const renderFunction = typeof children === 'function' ? children : render;
return (
<ReactRouterRoute
{...rest}
render={(props) => (
<>
<MatchPropagator />
{/* @ts-ignore else condition exists if renderFunction is undefined*/}
{renderFunction(props)}
</>
)}
/>
);
}
return (
<ReactRouterRoute {...rest}>
<MatchPropagator />
{children}
</ReactRouterRoute>
);
};
/**
* The match propogator that is part of the Route
*/
const MatchPropagator = () => {
const { executionContext } = useKibanaSharedUX().services;
const match = useRouteMatch();
useSharedUXExecutionContext(executionContext, {
type: 'application',
page: match.path,
id: Object.keys(match.params).length > 0 ? JSON.stringify(match.params) : undefined,
});
return null;
};