mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Moved logic to only send updated filters across Bridge to the Store (and added tests)
This commit is contained in:
@@ -11,7 +11,10 @@ env.beforeEach(() => {
|
||||
const Bridge = require('src/bridge').default;
|
||||
const Store = require('src/devtools/store').default;
|
||||
const { installHook } = require('src/hook');
|
||||
const { getDefaultComponentFilters } = require('src/utils');
|
||||
const {
|
||||
getDefaultComponentFilters,
|
||||
saveComponentFilters,
|
||||
} = require('src/utils');
|
||||
|
||||
// Fake timers let us flush Bridge operations between setup and assertions.
|
||||
jest.useFakeTimers();
|
||||
@@ -26,7 +29,8 @@ env.beforeEach(() => {
|
||||
originalConsoleError.apply(console, args);
|
||||
};
|
||||
|
||||
// Avoid "Invalid component filters" warning.
|
||||
// Initialize filters to a known good state.
|
||||
saveComponentFilters(getDefaultComponentFilters());
|
||||
global.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = getDefaultComponentFilters();
|
||||
|
||||
installHook(global);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import type Bridge from 'src/bridge';
|
||||
import type Store from 'src/devtools/store';
|
||||
|
||||
describe('Store component filters', () => {
|
||||
@@ -7,6 +8,7 @@ describe('Store component filters', () => {
|
||||
let ReactDOM;
|
||||
let TestUtils;
|
||||
let Types;
|
||||
let bridge: Bridge;
|
||||
let store: Store;
|
||||
let utils;
|
||||
|
||||
@@ -18,6 +20,7 @@ describe('Store component filters', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
bridge = global.bridge;
|
||||
store = global.store;
|
||||
store.collapseNodesByDefault = false;
|
||||
store.componentFilters = [];
|
||||
@@ -187,4 +190,34 @@ describe('Store component filters', () => {
|
||||
|
||||
expect(store).toMatchSnapshot('3: disable HOC filter');
|
||||
});
|
||||
|
||||
it('should not send a bridge update if the set of enabled filters has not changed', () => {
|
||||
act(() => (store.componentFilters = [utils.createHOCFilter(true)]));
|
||||
|
||||
bridge.addListener('updateComponentFilters', componentFilters => {
|
||||
throw Error('Unexpected component update');
|
||||
});
|
||||
|
||||
act(
|
||||
() =>
|
||||
(store.componentFilters = [
|
||||
utils.createHOCFilter(false),
|
||||
utils.createHOCFilter(true),
|
||||
])
|
||||
);
|
||||
act(
|
||||
() =>
|
||||
(store.componentFilters = [
|
||||
utils.createHOCFilter(true),
|
||||
utils.createLocationFilter('abc', false),
|
||||
])
|
||||
);
|
||||
act(
|
||||
() =>
|
||||
(store.componentFilters = [
|
||||
utils.createHOCFilter(true),
|
||||
utils.createElementTypeFilter(Types.ElementTypeHostComponent, false),
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
+27
-2
@@ -14,6 +14,7 @@ import {
|
||||
getSavedComponentFilters,
|
||||
saveComponentFilters,
|
||||
separateDisplayNameAndHOCs,
|
||||
shallowDiffers,
|
||||
utfDecodeString,
|
||||
} from '../utils';
|
||||
import { localStorageGetItem, localStorageSetItem } from '../storage';
|
||||
@@ -242,14 +243,38 @@ export default class Store extends EventEmitter<{|
|
||||
throw Error('Cannot modify filter preferences while profiling');
|
||||
}
|
||||
|
||||
// Filter updates are expensive to apply (since they impact the entire tree).
|
||||
// Let's determine if they've changed and avoid doing this work if they haven't.
|
||||
const prevEnabledComponentFilters = this._componentFilters.filter(
|
||||
filter => filter.isEnabled
|
||||
);
|
||||
const nextEnabledComponentFilters = value.filter(
|
||||
filter => filter.isEnabled
|
||||
);
|
||||
let haveEnabledFiltersChanged =
|
||||
prevEnabledComponentFilters.length !== nextEnabledComponentFilters.length;
|
||||
if (!haveEnabledFiltersChanged) {
|
||||
for (let i = 0; i < nextEnabledComponentFilters.length; i++) {
|
||||
const prevFilter = prevEnabledComponentFilters[i];
|
||||
const nextFilter = nextEnabledComponentFilters[i];
|
||||
if (shallowDiffers(prevFilter, nextFilter)) {
|
||||
haveEnabledFiltersChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._componentFilters = value;
|
||||
|
||||
// Update persisted filter preferences stored in localStorage.
|
||||
saveComponentFilters(value);
|
||||
|
||||
// Notify the renderer that filter prefernces have changed.
|
||||
// This is an expensive opreation; it unmounts and remounts the entire tree.
|
||||
this._bridge.send('updateComponentFilters', value);
|
||||
// This is an expensive opreation; it unmounts and remounts the entire tree,
|
||||
// so only do it if the set of enabled component filters has changed.
|
||||
if (haveEnabledFiltersChanged) {
|
||||
this._bridge.send('updateComponentFilters', value);
|
||||
}
|
||||
|
||||
this.emit('componentFilters');
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import Store from 'src/devtools/store';
|
||||
import Button from '../Button';
|
||||
import ButtonIcon from '../ButtonIcon';
|
||||
import Toggle from '../Toggle';
|
||||
import { shallowDiffers } from 'src/utils';
|
||||
import {
|
||||
ComponentFilterDisplayName,
|
||||
ComponentFilterElementType,
|
||||
@@ -221,7 +220,9 @@ export default function ComponentsSettings(_: {||}) {
|
||||
);
|
||||
|
||||
// Filter updates are expensive to apply (since they impact the entire tree).
|
||||
// Only apply them on unmount, and only if they've actually changed.
|
||||
// Only apply them on unmount.
|
||||
// The Store will avoid doing any expensive work unless they've changed.
|
||||
// We just want to batch the work in the event that they do change.
|
||||
const componentFiltersRef = useRef<Array<ComponentFilter>>(componentFilters);
|
||||
useEffect(() => {
|
||||
componentFiltersRef.current = componentFilters;
|
||||
@@ -229,25 +230,7 @@ export default function ComponentsSettings(_: {||}) {
|
||||
}, [componentFilters]);
|
||||
useEffect(
|
||||
() => () => {
|
||||
const prevComponentFilters = store.componentFilters;
|
||||
const nextComponentFilters = componentFiltersRef.current;
|
||||
|
||||
let haveFiltersChanged =
|
||||
prevComponentFilters.length !== nextComponentFilters.length;
|
||||
if (!haveFiltersChanged) {
|
||||
for (let i = 0; i < nextComponentFilters.length; i++) {
|
||||
if (
|
||||
shallowDiffers(prevComponentFilters[i], nextComponentFilters[i])
|
||||
) {
|
||||
haveFiltersChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (haveFiltersChanged) {
|
||||
store.componentFilters = [...nextComponentFilters];
|
||||
}
|
||||
store.componentFilters = [...componentFiltersRef.current];
|
||||
},
|
||||
[store]
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user