useCleanQueryParamsOnRouteLeave.tsx 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import {useCallback, useEffect} from 'react';
  2. import {browserHistory} from 'react-router';
  3. import type {Location} from 'history';
  4. import {useLocation} from 'sentry/utils/useLocation';
  5. type Opts<Q> = {
  6. fieldsToClean: string[];
  7. shouldClean?: (newLocation: Location<Q>) => boolean;
  8. };
  9. export function handleRouteLeave<Q extends object>({
  10. fieldsToClean,
  11. newLocation,
  12. oldPathname,
  13. }: {
  14. fieldsToClean: string[];
  15. newLocation: Location<Q>;
  16. oldPathname: string;
  17. }) {
  18. const hasSomeValues = fieldsToClean.some(
  19. field => newLocation.query[field] !== undefined
  20. );
  21. if (newLocation.pathname === oldPathname || !hasSomeValues) {
  22. return;
  23. }
  24. // Removes fields from the URL on route leave so that the parameters will
  25. // not interfere with other pages
  26. const query = fieldsToClean.reduce(
  27. (newQuery, field) => {
  28. newQuery[field] = undefined;
  29. return newQuery;
  30. },
  31. {...newLocation.query}
  32. );
  33. browserHistory.replace({
  34. pathname: newLocation.pathname,
  35. query,
  36. });
  37. }
  38. function useCleanQueryParamsOnRouteLeave<Q>({fieldsToClean, shouldClean}: Opts<Q>) {
  39. const location = useLocation();
  40. const onRouteLeave = useCallback(
  41. newLocation => {
  42. if (!shouldClean || shouldClean(newLocation)) {
  43. handleRouteLeave({
  44. fieldsToClean,
  45. newLocation,
  46. oldPathname: location.pathname,
  47. });
  48. }
  49. },
  50. [shouldClean, fieldsToClean, location.pathname]
  51. );
  52. useEffect(() => {
  53. return browserHistory.listen(onRouteLeave);
  54. }, [onRouteLeave]);
  55. }
  56. export default useCleanQueryParamsOnRouteLeave;