From 507f5c95e58f2d365fdf343e97a4a3ad79130aac Mon Sep 17 00:00:00 2001 From: Arkadiusz Biel - bielu <2244074+bielu@users.noreply.github.com> Date: Sun, 11 Oct 2026 23:24:59 +0100 Subject: [PATCH] Fix browser freeze when clicking a component on the Browse page PageBrowse replaced the state initialized by SystemManagedList, dropping `sequence: 0`. The first row click then computed `undefined + 1`, so `sequence` became NaN. ComponentList.componentDidUpdate compares `this.props.sequence !== prevProps.sequence`, which is always true for NaN, so it kept calling setState and re-rendering the list forever. Keep the inherited state when PageBrowse sets its own, and add a regression test. Fixes #1130 Co-Authored-By: Claude Opus 5.5 --- .../Navigation/Pages/PageBrowse/PageBrowse.js | 2 ++ src/components/__tests__/PageBrowse.test.js | 23 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/components/Navigation/Pages/PageBrowse/PageBrowse.js b/src/components/Navigation/Pages/PageBrowse/PageBrowse.js index 38a19dda..9a617a43 100644 --- a/src/components/Navigation/Pages/PageBrowse/PageBrowse.js +++ b/src/components/Navigation/Pages/PageBrowse/PageBrowse.js @@ -31,7 +31,9 @@ import searchSvg from '../../../../images/icons/searchSvg.svg' class PageBrowse extends SystemManagedList { constructor(props) { super(props) + // keep the state initialized by SystemManagedList (e.g. sequence), otherwise sequence + 1 ends up as NaN this.state = { + ...this.state, activeSort: 'releaseDate-desc', searchFocused: false, selectedProvider: providers[0], diff --git a/src/components/__tests__/PageBrowse.test.js b/src/components/__tests__/PageBrowse.test.js index a8b3059a..ac4e0fee 100644 --- a/src/components/__tests__/PageBrowse.test.js +++ b/src/components/__tests__/PageBrowse.test.js @@ -1,11 +1,17 @@ import React from 'react' -import { render } from '@testing-library/react' +import { render, act } from '@testing-library/react' import { Provider } from 'react-redux' import { BrowserRouter } from 'react-router-dom' import configureMockStore from 'redux-mock-store' import thunk from 'redux-thunk' import ConnectedPageBrowse from '../Navigation/Pages/PageBrowse' +let mockComponentListProps = null +jest.mock('../ComponentList', () => props => { + mockComponentListProps = props + return null +}) + const middlewares = [thunk] const mockStore = configureMockStore(middlewares) @@ -51,7 +57,22 @@ const renderWithProviders = (ui, { store = defaultStore } = {}) => { } describe('PageBrowse', () => { + beforeEach(() => { + mockComponentListProps = null + }) + it('renders without crashing', () => { renderWithProviders() }) + + it('keeps a numeric sequence when a component is expanded', async () => { + renderWithProviders() + expect(mockComponentListProps.sequence).toBe(0) + + const component = { type: 'npm', provider: 'npmjs', name: 'test', revision: '1.0.0' } + await act(async () => { + await mockComponentListProps.onChange(component, { ...component, expanded: true }) + }) + expect(mockComponentListProps.sequence).toBe(1) + }) })