Skip to content

Commit

Permalink
Avoid routing when passed object does not change
Browse files Browse the repository at this point in the history
  • Loading branch information
danrot committed Mar 4, 2020
1 parent c7b7c9b commit 6a5660c
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
Expand Up @@ -37,6 +37,20 @@ function tryParse(value: ?string) {
return parseFloat(value);
}

function equalBindings(value1, value2) {
if (typeof(value1) !== 'object' || typeof(value2) !== 'object') {
return value1 == value2;
}

const objectKeys = Object.keys(value1);

if (!equal(objectKeys, Object.keys(value2))) {
return false;
}

return objectKeys.every((key) => equalBindings(value1[key], value2[key]));
}

function addValueToSearchParameters(searchParameters: URLSearchParams, value: Object, path: string) {
if (Array.isArray(value)) {
addArrayToSearchParameters(searchParameters, value, path);
Expand Down Expand Up @@ -302,7 +316,7 @@ export default class Router {
: this.bindingDefaults.get(key);

// Type unsafe comparison to not trigger a new navigation when only data type changes
if (value != observableValue.get()) {
if (!equalBindings(value, observableValue.get())) {
observableValue.set(value);
}
}
Expand Down
Expand Up @@ -1020,6 +1020,56 @@ test('Binding should not be updated if only data type changes', () => {
expect(page.set.mock.calls).not.toContainEqual(['2']);
});

test('Binding should not be updated if the same object is set again', () => {
routeRegistry.getAll.mockReturnValue({
list: {
name: 'list',
type: 'list',
path: '/list',
attributeDefaults: {},
},
});

const filter = jest.fn(() => ({
get: jest.fn().mockReturnValue({}),
set: jest.fn(),
observe: jest.fn(),
intercept: jest.fn(),
}))();

const history = createMemoryHistory();
const router = new Router(history);
router.bind('filter', filter);

router.navigate('list', {filter: {}});
expect(filter.set.mock.calls).not.toContainEqual([{}]);
});

test('Binding should be updated if another object is set', () => {
routeRegistry.getAll.mockReturnValue({
list: {
name: 'list',
type: 'list',
path: '/list',
attributeDefaults: {},
},
});

const filter = jest.fn(() => ({
get: jest.fn().mockReturnValue({}),
set: jest.fn(),
observe: jest.fn(),
intercept: jest.fn(),
}))();

const history = createMemoryHistory();
const router = new Router(history);
router.bind('filter', filter);

router.navigate('list', {filter: {test: {eq: 'Test'}}});
expect(filter.set.mock.calls).toContainEqual([{test: {eq: 'Test'}}]);
});

test('Navigate to child route using state', () => {
const formRoute = extendObservable({}, {
name: 'sulu_snippet.form',
Expand Down

0 comments on commit 6a5660c

Please sign in to comment.