mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +01:00
[DevTools] Reset forced states when changing component filters (#34929)
This commit is contained in:
parent
6fb7754494
commit
c9ddee7e36
|
|
@ -116,6 +116,16 @@ function shouldIgnoreConsoleErrorOrWarn(args) {
|
|||
return false;
|
||||
}
|
||||
|
||||
const maybeError = args[1];
|
||||
if (
|
||||
maybeError !== null &&
|
||||
typeof maybeError === 'object' &&
|
||||
maybeError.message === 'Simulated error coming from DevTools'
|
||||
) {
|
||||
// Error from forcing an error boundary.
|
||||
return true;
|
||||
}
|
||||
|
||||
return global._ignoredErrorOrWarningMessages.some(errorOrWarningMessage => {
|
||||
return firstArg.indexOf(errorOrWarningMessage) !== -1;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -18,12 +18,14 @@ import {
|
|||
describe('Store component filters', () => {
|
||||
let React;
|
||||
let Types;
|
||||
let agent;
|
||||
let bridge: FrontendBridge;
|
||||
let store: Store;
|
||||
let utils;
|
||||
let actAsync;
|
||||
|
||||
beforeEach(() => {
|
||||
agent = global.agent;
|
||||
bridge = global.bridge;
|
||||
store = global.store;
|
||||
store.collapseNodesByDefault = false;
|
||||
|
|
@ -740,4 +742,80 @@ describe('Store component filters', () => {
|
|||
`);
|
||||
});
|
||||
});
|
||||
|
||||
// @reactVersion >= 16.6
|
||||
it('resets forced error and fallback states when filters are changed', async () => {
|
||||
store.componentFilters = [];
|
||||
class ErrorBoundary extends React.Component {
|
||||
state = {hasError: false};
|
||||
|
||||
static getDerivedStateFromError() {
|
||||
return {hasError: true};
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return <div key="did-error" />;
|
||||
}
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<>
|
||||
<React.Suspense fallback={<div key="loading" />}>
|
||||
<div key="suspense-content" />
|
||||
</React.Suspense>
|
||||
<ErrorBoundary>
|
||||
<div key="error-content" />
|
||||
</ErrorBoundary>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
await actAsync(async () => {
|
||||
render(<App />);
|
||||
});
|
||||
const rendererID = utils.getRendererID();
|
||||
await actAsync(() => {
|
||||
agent.overrideSuspense({
|
||||
id: store.getElementIDAtIndex(2),
|
||||
rendererID,
|
||||
forceFallback: true,
|
||||
});
|
||||
agent.overrideError({
|
||||
id: store.getElementIDAtIndex(4),
|
||||
rendererID,
|
||||
forceError: true,
|
||||
});
|
||||
});
|
||||
|
||||
expect(store).toMatchInlineSnapshot(`
|
||||
[root]
|
||||
▾ <App>
|
||||
▾ <Suspense>
|
||||
<div key="loading">
|
||||
▾ <ErrorBoundary>
|
||||
<div key="did-error">
|
||||
[suspense-root] rects={[]}
|
||||
<Suspense name="App" rects={[]}>
|
||||
`);
|
||||
|
||||
await actAsync(() => {
|
||||
store.componentFilters = [
|
||||
utils.createElementTypeFilter(Types.ElementTypeFunction, true),
|
||||
];
|
||||
});
|
||||
|
||||
expect(store).toMatchInlineSnapshot(`
|
||||
[root]
|
||||
▾ <Suspense>
|
||||
<div key="suspense-content">
|
||||
▾ <ErrorBoundary>
|
||||
<div key="error-content">
|
||||
[suspense-root] rects={[]}
|
||||
<Suspense name="Unknown" rects={[]}>
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1512,6 +1512,11 @@ export function attach(
|
|||
throw Error('Cannot modify filter preferences while profiling');
|
||||
}
|
||||
|
||||
const previousForcedFallbacks =
|
||||
forceFallbackForFibers.size > 0 ? new Set(forceFallbackForFibers) : null;
|
||||
const previousForcedErrors =
|
||||
forceErrorForFibers.size > 0 ? new Map(forceErrorForFibers) : null;
|
||||
|
||||
// Recursively unmount all roots.
|
||||
hook.getFiberRoots(rendererID).forEach(root => {
|
||||
const rootInstance = rootToFiberInstanceMap.get(root);
|
||||
|
|
@ -1532,6 +1537,41 @@ export function attach(
|
|||
// Reset pseudo counters so that new path selections will be persisted.
|
||||
rootDisplayNameCounter.clear();
|
||||
|
||||
// We just cleared all the forced states. Schedule updates on the affected Fibers
|
||||
// so that we get their initial states again according to the new filters.
|
||||
if (typeof scheduleUpdate === 'function') {
|
||||
if (previousForcedFallbacks !== null) {
|
||||
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||
for (const fiber of previousForcedFallbacks) {
|
||||
if (typeof scheduleRetry === 'function') {
|
||||
scheduleRetry(fiber);
|
||||
} else {
|
||||
scheduleUpdate(fiber);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
previousForcedErrors !== null &&
|
||||
typeof setErrorHandler === 'function'
|
||||
) {
|
||||
// Unlike for Suspense, disabling the forced error state requires setting
|
||||
// the status to false first. `shouldErrorFiberAccordingToMap` will clear
|
||||
// the Fibers later.
|
||||
setErrorHandler(shouldErrorFiberAccordingToMap);
|
||||
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||
for (const [fiber, shouldError] of previousForcedErrors) {
|
||||
forceErrorForFibers.set(fiber, false);
|
||||
if (shouldError) {
|
||||
if (typeof scheduleRetry === 'function') {
|
||||
scheduleRetry(fiber);
|
||||
} else {
|
||||
scheduleUpdate(fiber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively re-mount all roots with new filter criteria applied.
|
||||
hook.getFiberRoots(rendererID).forEach(root => {
|
||||
const current = root.current;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user