Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions packages/react-devtools-shared/src/__tests__/store-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ describe('Store', () => {
let act;
let actAsync;
let bridge;
let createDisplayNameFilter;
let getRendererID;
let legacyRender;
let previousComponentFilters;
let store;
let withErrorsOrWarningsIgnored;

Expand All @@ -29,6 +31,8 @@ describe('Store', () => {
bridge = global.bridge;
store = global.store;

previousComponentFilters = store.componentFilters;

React = require('react');
ReactDOM = require('react-dom');
ReactDOMClient = require('react-dom/client');
Expand All @@ -38,9 +42,14 @@ describe('Store', () => {
actAsync = utils.actAsync;
getRendererID = utils.getRendererID;
legacyRender = utils.legacyRender;
createDisplayNameFilter = utils.createDisplayNameFilter;
withErrorsOrWarningsIgnored = utils.withErrorsOrWarningsIgnored;
});

afterEach(() => {
store.componentFilters = previousComponentFilters;
});

const {render, unmount, createContainer} = getVersionedRenderImplementation();

// @reactVersion >= 18.0
Expand Down Expand Up @@ -129,6 +138,72 @@ describe('Store', () => {
`);
});

it('should handle reorder of filtered elements', async () => {
function IgnoreMePassthrough({children}) {
return children;
}
function PassThrough({children}) {
return children;
}

await actAsync(
async () =>
(store.componentFilters = [createDisplayNameFilter('^IgnoreMe', true)]),
);

await act(() => {
render(
<PassThrough key="e" name="e">
<IgnoreMePassthrough key="e1">
<PassThrough name="e-child-one">
<p>e1</p>
</PassThrough>
</IgnoreMePassthrough>
<IgnoreMePassthrough key="e2">
<PassThrough name="e-child-two">
<div>e2</div>
</PassThrough>
</IgnoreMePassthrough>
</PassThrough>,
);
});

expect(store).toMatchInlineSnapshot(`
[root]
▾ <PassThrough key="e">
▾ <PassThrough>
<p>
▾ <PassThrough>
<div>
`);

await act(() => {
render(
<PassThrough key="e" name="e">
<IgnoreMePassthrough key="e2">
<PassThrough name="e-child-two">
<div>e2</div>
</PassThrough>
</IgnoreMePassthrough>
<IgnoreMePassthrough key="e1">
<PassThrough name="e-child-one">
<p>e1</p>
</PassThrough>
</IgnoreMePassthrough>
</PassThrough>,
);
});

expect(store).toMatchInlineSnapshot(`
[root]
▾ <PassThrough key="e">
▾ <PassThrough>
<div>
▾ <PassThrough>
<p>
`);
});

describe('StrictMode compliance', () => {
it('should mark strict root elements as strict', async () => {
const App = () => <Component />;
Expand Down
5 changes: 5 additions & 0 deletions packages/react-devtools-shared/src/backend/fiber/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3612,6 +3612,11 @@ export function attach(
shouldResetChildren = true;
}
} else if (prevChild !== null && shouldFilterFiber(nextChild)) {
// The filtered instance could've reordered.
if (prevChild !== prevChildAtSameIndex) {
shouldResetChildren = true;
}

// If this Fiber should be filtered, we need to still update its children.
// This relies on an alternate since we don't have an Instance with the previous
// child on it. Ideally, the reconciliation wouldn't need previous Fibers that
Expand Down
Loading