You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

withRouter.tsx 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2024 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. import * as React from 'react';
  21. import { useMemo } from 'react';
  22. import {
  23. Params,
  24. useLocation as useLocationRouter,
  25. useNavigate,
  26. useParams,
  27. useSearchParams,
  28. } from 'react-router-dom';
  29. import { searchParamsToQuery } from '../../helpers/router';
  30. import { queryToSearchString } from '../../helpers/urls';
  31. import { Location, Router } from '../../types/router';
  32. import { getWrappedDisplayName } from './utils';
  33. export interface WithRouterProps {
  34. location: Location;
  35. params: Params;
  36. router: Router;
  37. }
  38. export function withRouter<P extends Partial<WithRouterProps>>(
  39. WrappedComponent: React.ComponentType<React.PropsWithChildren<P>>,
  40. ): React.ComponentType<React.PropsWithChildren<Omit<P, keyof WithRouterProps>>> {
  41. function ComponentWithRouterProp(props: Readonly<P>) {
  42. const router = useRouter();
  43. const params = useParams();
  44. const location = useLocation();
  45. return <WrappedComponent {...props} location={location} params={params} router={router} />;
  46. }
  47. (ComponentWithRouterProp as React.FC<React.PropsWithChildren<P>>).displayName =
  48. getWrappedDisplayName(WrappedComponent, 'withRouter');
  49. return ComponentWithRouterProp;
  50. }
  51. export function useRouter() {
  52. const navigate = useNavigate();
  53. const [searchParams, setSearchParams] = useSearchParams();
  54. return React.useMemo(
  55. () => ({
  56. replace: (path: string | Partial<Location>) => {
  57. if ((path as Location).query) {
  58. path.search = queryToSearchString((path as Location).query);
  59. }
  60. navigate(path, { replace: true });
  61. },
  62. push: (path: string | Partial<Location>) => {
  63. if ((path as Location).query) {
  64. path.search = queryToSearchString((path as Location).query);
  65. }
  66. navigate(path);
  67. },
  68. navigate,
  69. searchParams,
  70. setSearchParams,
  71. }),
  72. [navigate, searchParams, setSearchParams],
  73. );
  74. }
  75. export function useLocation() {
  76. const location = useLocationRouter();
  77. return useMemo(
  78. () => ({ ...location, query: searchParamsToQuery(new URLSearchParams(location.search)) }),
  79. [location],
  80. );
  81. }