From 5a153fa925fe537cf3aa6857f0bba4c1675437d4 Mon Sep 17 00:00:00 2001 From: Yoronex <me@roykakkenberg.nl> Date: Mon, 4 Mar 2024 22:29:29 +0100 Subject: [PATCH] Fix in-place redux state updates causing crashes --- src/App.tsx | 13 ++++++++++++- .../entities/company/CompanyContactList.tsx | 3 +-- src/components/entities/company/CompanySelector.tsx | 2 +- src/components/entities/contact/ContactSelector.tsx | 2 +- .../entities/contract/ContractCompactTable.tsx | 2 +- .../entities/contract/ContractProductList.tsx | 2 +- .../entities/contract/ContractProductRow.tsx | 2 +- src/components/entities/product/ProductSelector.tsx | 2 +- .../entities/product/ProductVatSelector.tsx | 2 +- .../productcategories/ProductCategorySelector.tsx | 2 +- src/components/entities/user/UserSelector.tsx | 2 +- src/components/files/FilesList.tsx | 2 +- src/helpers/contact.ts | 7 ++++--- 13 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 9cbaa36..737526d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -36,6 +36,17 @@ class App extends React.Component<{}, State> { })); } + private getContent() { + if (this.state.hasError) { + return ( + <AlertContainer /> + ); + } + return ( + <Routes /> + ); + } + public render() { if (this.state.hasError) { return ( @@ -46,7 +57,7 @@ class App extends React.Component<{}, State> { return ( <Provider store={store}> <ReduxRouter history={history} routerSelector={routerSelector}> - <Routes /> + {this.getContent()} </ReduxRouter> </Provider> ); diff --git a/src/components/entities/company/CompanyContactList.tsx b/src/components/entities/company/CompanyContactList.tsx index 715466b..2abe95c 100644 --- a/src/components/entities/company/CompanyContactList.tsx +++ b/src/components/entities/company/CompanyContactList.tsx @@ -37,8 +37,7 @@ class CompanyContactList extends React.Component<Props, State> { ); } - const { contacts } = company; - sortContactsByFunction(contacts, true); + const contacts = sortContactsByFunction(company.contacts, true); if (contacts.length === 0) { return ( diff --git a/src/components/entities/company/CompanySelector.tsx b/src/components/entities/company/CompanySelector.tsx index f1b2b0d..de28c50 100644 --- a/src/components/entities/company/CompanySelector.tsx +++ b/src/components/entities/company/CompanySelector.tsx @@ -18,7 +18,7 @@ function CompanySelector(props: Props & DropdownProps) { const { value, onChange, options, disabled, } = props; - const dropdownOptions = options.filter((c) => c.status !== CompanyStatus.INACTIVE) + const dropdownOptions = [...options].filter((c) => c.status !== CompanyStatus.INACTIVE) .sort((c1, c2) => { const n1 = c1.name.toUpperCase(); const n2 = c2.name.toUpperCase(); diff --git a/src/components/entities/contact/ContactSelector.tsx b/src/components/entities/contact/ContactSelector.tsx index da5600f..241aa6d 100644 --- a/src/components/entities/contact/ContactSelector.tsx +++ b/src/components/entities/contact/ContactSelector.tsx @@ -21,7 +21,7 @@ function ContactSelector(props: Props & DropdownProps) { value, onChange, options, disabled, companyId, placeholder, } = props; - const dropdownOptions = sortContactsByFunction(options, true) + const dropdownOptions = sortContactsByFunction([...options], true) .filter((c) => c.companyId === companyId && c.function !== ContactFunction.OLD) .map((x) => ({ key: x.id, diff --git a/src/components/entities/contract/ContractCompactTable.tsx b/src/components/entities/contract/ContractCompactTable.tsx index 1d35239..da87c03 100644 --- a/src/components/entities/contract/ContractCompactTable.tsx +++ b/src/components/entities/contract/ContractCompactTable.tsx @@ -110,7 +110,7 @@ class ContractCompactTable extends React.Component<Props, State> { </Table.Row> </Table.Header> <Table.Body> - {productInstances + {[...productInstances] .sort((a, b) => { return b.updatedAt.getTime() - a.updatedAt.getTime(); }) .map((p) => <ContractCompactRow key={p.id} contract={p.contract} />)} </Table.Body> diff --git a/src/components/entities/contract/ContractProductList.tsx b/src/components/entities/contract/ContractProductList.tsx index 7bfdba1..ffce9bb 100644 --- a/src/components/entities/contract/ContractProductList.tsx +++ b/src/components/entities/contract/ContractProductList.tsx @@ -130,7 +130,7 @@ class ContractProductList extends React.Component<Props, State> { </Table.Header> <Table.Body> - {products.sort((a, b) => a.id - b.id).map((product) => ( + {[...products].sort((a, b) => a.id - b.id).map((product) => ( <ContractProductRow key={product.id} productInstance={product} diff --git a/src/components/entities/contract/ContractProductRow.tsx b/src/components/entities/contract/ContractProductRow.tsx index 626a1cc..1965f1c 100644 --- a/src/components/entities/contract/ContractProductRow.tsx +++ b/src/components/entities/contract/ContractProductRow.tsx @@ -22,7 +22,7 @@ function showRecentStatus(productInstance: ProductInstance): string { return null; }); - const sortedArray = statusArray.sort((a, b) => (b.createdAt.getTime() - a.createdAt.getTime())); + const sortedArray = [...statusArray].sort((a, b) => (b.createdAt.getTime() - a.createdAt.getTime())); if (sortedArray.length === 0) return ''; return sortedArray[0].subType!; } diff --git a/src/components/entities/product/ProductSelector.tsx b/src/components/entities/product/ProductSelector.tsx index 77341a0..7ede920 100644 --- a/src/components/entities/product/ProductSelector.tsx +++ b/src/components/entities/product/ProductSelector.tsx @@ -20,7 +20,7 @@ function ProductSelector(props: Props & DropdownProps) { const { value, onChange, options, } = props; - const dropdownOptions = options + const dropdownOptions = [...options] .filter((p) => p.status === ProductStatus.ACTIVE) .sort((p1, p2) => { const n1 = currentLanguage === 'nl-NL' ? p1.nameDutch.toUpperCase() : p1.nameEnglish.toUpperCase(); diff --git a/src/components/entities/product/ProductVatSelector.tsx b/src/components/entities/product/ProductVatSelector.tsx index ba92893..d2ee4ad 100644 --- a/src/components/entities/product/ProductVatSelector.tsx +++ b/src/components/entities/product/ProductVatSelector.tsx @@ -18,7 +18,7 @@ function ProductVATSelector(props: Props & DropdownProps) { value, onChange, options, } = props; - const dropdownOptions = options.sort((v1, v2) => { + const dropdownOptions = [...options].sort((v1, v2) => { return v1.amount >= v2.amount ? 1 : -1; }).map((x) => ({ key: x.id, diff --git a/src/components/entities/productcategories/ProductCategorySelector.tsx b/src/components/entities/productcategories/ProductCategorySelector.tsx index 7fa1bed..666b898 100644 --- a/src/components/entities/productcategories/ProductCategorySelector.tsx +++ b/src/components/entities/productcategories/ProductCategorySelector.tsx @@ -17,7 +17,7 @@ function ProductCategorySelector(props: Props & DropdownProps) { const { value, onChange, options, } = props; - const dropdownOptions = options.sort((c1, c2) => { + const dropdownOptions = [...options].sort((c1, c2) => { const n1 = c1.name.toUpperCase(); const n2 = c2.name.toUpperCase(); if (n1 < n2) return -1; diff --git a/src/components/entities/user/UserSelector.tsx b/src/components/entities/user/UserSelector.tsx index 81bc3ea..0330ebf 100644 --- a/src/components/entities/user/UserSelector.tsx +++ b/src/components/entities/user/UserSelector.tsx @@ -25,7 +25,7 @@ function UserSelector(props: Props & DropdownProps) { const filteredOptions = role !== undefined ? options.filter((u) => u.roles.includes(role)) : options; - const dropdownOptions = filteredOptions.sort((u1, u2) => { + const dropdownOptions = [...filteredOptions].sort((u1, u2) => { const n1 = formatContactName(u1.firstName, u1.lastNamePreposition, u1.lastName).toUpperCase(); const n2 = formatContactName(u2.firstName, u2.lastNamePreposition, u2.lastName).toUpperCase(); if (n1 < n2) return -1; diff --git a/src/components/files/FilesList.tsx b/src/components/files/FilesList.tsx index 5e5cea6..9d2a6c5 100644 --- a/src/components/files/FilesList.tsx +++ b/src/components/files/FilesList.tsx @@ -83,7 +83,7 @@ class FilesList extends React.Component<Props, State> { <Table compact fixed singleLine unstackable className="files"> <Table.Body> {createRow} - {files + {[...files] .sort((a, b) => { return b.createdAt.getTime() - a.createdAt.getTime(); }) .map((file) => ( <SingleFile diff --git a/src/helpers/contact.ts b/src/helpers/contact.ts index 21b2e28..03918b4 100644 --- a/src/helpers/contact.ts +++ b/src/helpers/contact.ts @@ -45,8 +45,9 @@ export function sortContactsByFunction( contacts: Contact[] | ContactSummary[], sortAlphabetically?: boolean, ): Contact[] | ContactSummary[] { + let c = [...contacts]; if (sortAlphabetically) { - contacts.sort((c1, c2) => { + c.sort((c1, c2) => { const n1 = formatContactName(c1.firstName, c1.lastNamePreposition, c1.lastName).toUpperCase(); const n2 = formatContactName(c2.firstName, c2.lastNamePreposition, c2.lastName).toUpperCase(); if (n1 < n2) return -1; @@ -55,7 +56,7 @@ export function sortContactsByFunction( }); } - contacts.sort((c1, c2) => { + c.sort((c1, c2) => { switch (c1.function) { case ContactFunction.PRIMARY: return -1; case ContactFunction.NORMAL: @@ -79,5 +80,5 @@ export function sortContactsByFunction( } }); - return contacts; + return c; }