Fix "PageChangeEffect does not run when changing view on the same object" (#12196)
Fixes https://github.com/twentyhq/core-team-issues/issues/950 This issue was due to the memoization inside `useIsMatchingLocation`, which was rerendered only if the pathname changed but not the search params. After discussion with @lucasbordeau, we decided to remove the hook `useIsMatchingLocation` and to create an equivalent util function which takes the location as an argument. --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
@ -0,0 +1,89 @@
|
||||
import { AppBasePath } from '@/types/AppBasePath';
|
||||
import { isMatchingLocation } from '../isMatchingLocation';
|
||||
|
||||
describe('isMatchingLocation', () => {
|
||||
it('returns true when paths match with no basePath', () => {
|
||||
const location = {
|
||||
pathname: '/example',
|
||||
state: null,
|
||||
key: 'test-key',
|
||||
search: '',
|
||||
hash: '',
|
||||
};
|
||||
const result = isMatchingLocation(location, '/example');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when paths do not match with no basePath', () => {
|
||||
const location = {
|
||||
pathname: '/example',
|
||||
state: null,
|
||||
key: 'test-key',
|
||||
search: '',
|
||||
hash: '',
|
||||
};
|
||||
const result = isMatchingLocation(location, '/non-match');
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true when paths match with basePath', () => {
|
||||
const location = {
|
||||
pathname: `${AppBasePath.Settings}/example`,
|
||||
state: null,
|
||||
key: 'test-key',
|
||||
search: '',
|
||||
hash: '',
|
||||
};
|
||||
const result = isMatchingLocation(
|
||||
location,
|
||||
'example',
|
||||
AppBasePath.Settings,
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when paths do not match with basePath', () => {
|
||||
const location = {
|
||||
pathname: `${AppBasePath.Settings}/example`,
|
||||
state: null,
|
||||
key: 'test-key',
|
||||
search: '',
|
||||
hash: '',
|
||||
};
|
||||
|
||||
const result = isMatchingLocation(
|
||||
location,
|
||||
'non-match',
|
||||
AppBasePath.Settings,
|
||||
);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('handles trailing slashes in basePath correctly', () => {
|
||||
const location = {
|
||||
pathname: `${AppBasePath.Settings}/example`,
|
||||
state: null,
|
||||
key: 'test-key',
|
||||
search: '',
|
||||
hash: '',
|
||||
};
|
||||
const result = isMatchingLocation(
|
||||
location,
|
||||
'example',
|
||||
(AppBasePath.Settings + '/') as AppBasePath,
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('handles paths without basePath correctly', () => {
|
||||
const location = {
|
||||
pathname: '/example',
|
||||
state: null,
|
||||
key: 'test-key',
|
||||
search: '',
|
||||
hash: '',
|
||||
};
|
||||
const result = isMatchingLocation(location, '/example');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
26
packages/twenty-front/src/utils/isMatchingLocation.ts
Normal file
26
packages/twenty-front/src/utils/isMatchingLocation.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { Location, matchPath } from 'react-router-dom';
|
||||
|
||||
import { AppBasePath } from '@/types/AppBasePath';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
const addTrailingSlash = (path: string) =>
|
||||
path.endsWith('/') ? path : path + '/';
|
||||
|
||||
const getConstructedPath = (path: string, basePath?: AppBasePath) => {
|
||||
if (!isNonEmptyString(basePath)) return path;
|
||||
|
||||
return addTrailingSlash(basePath) + path;
|
||||
};
|
||||
|
||||
export const isMatchingLocation = (
|
||||
location: Location,
|
||||
path: string,
|
||||
basePath?: AppBasePath,
|
||||
): boolean => {
|
||||
const match = matchPath(
|
||||
getConstructedPath(path, basePath),
|
||||
location.pathname,
|
||||
);
|
||||
return isDefined(match);
|
||||
};
|
||||
Reference in New Issue
Block a user