From 3624887548c5f9e0948bc431cfde6e1358f5fe52 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 13:25:24 +1200 Subject: [PATCH 01/14] Add memoization of SearchBar --- src/widgets/SearchBar.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/widgets/SearchBar.js b/src/widgets/SearchBar.js index c6dd718ec..384fe846e 100644 --- a/src/widgets/SearchBar.js +++ b/src/widgets/SearchBar.js @@ -18,7 +18,10 @@ import { debounce } from '../utilities/index'; * with a magnifying glass icon and clear button. * * Debounces input by the user, such that the onChangeText callback - * is only invoked once every `debounceTimeout` + * is only invoked once every `debounceTimeout`. + * + * NOTE: This component is exported MEMOIZED. See below for propsAreEqual + * implementation. * * @param {String} color Color of the entire component (monochrome only). * @param {String} onChangeText Callback for changing text (debounced). @@ -30,7 +33,7 @@ import { debounce } from '../utilities/index'; * @param {String} debounceTimeout Time in milliseconds to debounce the onChangeText callback. * @param {Func} onFocusOrBlur Callback for onBlur and onFocus events. */ -export const SearchBar = ({ +export const SearchBarComponent = ({ color, onChangeText, value, @@ -94,6 +97,13 @@ export const SearchBar = ({ ); }; +/** + * Only re-render this component when the value prop changes. + */ +const propsAreEqual = ({ value: prevValue }, { value: nextValue }) => prevValue === nextValue; + +export const SearchBar = React.memo(SearchBarComponent, propsAreEqual); + const defaultStyles = StyleSheet.create({ container: { borderBottomWidth: 1, @@ -109,7 +119,7 @@ const defaultStyles = StyleSheet.create({ }, }); -SearchBar.defaultProps = { +SearchBarComponent.defaultProps = { debounceTimeout: 250, textInputStyle: defaultStyles.textInput, viewStyle: defaultStyles.container, @@ -120,7 +130,7 @@ SearchBar.defaultProps = { onFocusOrBlur: null, }; -SearchBar.propTypes = { +SearchBarComponent.propTypes = { color: PropTypes.string, debounceTimeout: PropTypes.number, onChangeText: PropTypes.func.isRequired, From a7266e39bc283e12bbf5ea2510a0b7e185751c63 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 14:50:06 +1200 Subject: [PATCH 02/14] Add memoization to DataTablePageModal --- .../dataTableUtilities/getPageInitialiser.js | 2 +- src/widgets/modals/DataTablePageModal.js | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/pages/dataTableUtilities/getPageInitialiser.js b/src/pages/dataTableUtilities/getPageInitialiser.js index 1653ddfff..6f2d6de89 100644 --- a/src/pages/dataTableUtilities/getPageInitialiser.js +++ b/src/pages/dataTableUtilities/getPageInitialiser.js @@ -142,7 +142,7 @@ const stocktakesInitialiser = () => { * @returns {object} */ const stocktakeBatchInitialiser = stocktakeItem => ({ - stocktakeItem, + pageObject: stocktakeItem, backingData: stocktakeItem.batches, data: stocktakeItem.batches.slice(), keyExtractor: recordKeyExtractor, diff --git a/src/widgets/modals/DataTablePageModal.js b/src/widgets/modals/DataTablePageModal.js index d93ca511a..24404bb52 100644 --- a/src/widgets/modals/DataTablePageModal.js +++ b/src/widgets/modals/DataTablePageModal.js @@ -1,3 +1,4 @@ +/* eslint-disable import/prefer-default-export */ /* eslint-disable react/forbid-prop-types */ /** * mSupply Mobile @@ -31,6 +32,9 @@ import NewSocktakeBatchModal from './NewStocktakeBatchModal'; /** * Wrapper around ModalContainer, containing common modals used in various * DataTable pages. + * + * NOTE: Exported component is MEMOIZED - see below for propsAreEqual implementation. + * * @prop {Bool} fullScreen Force the modal to cover the entire screen. * @prop {Bool} isOpen Whether the modal is open * @prop {Func} onClose A function to call if the close x is pressed @@ -44,7 +48,7 @@ const ADDITIONAL_MODAL_PROPS = { [MODAL_KEYS.ENFORCE_STOCKTAKE_REASON]: { noCancel: true, fullScreen: true }, }; -export const DataTablePageModal = ({ +const DataTablePageModalComponent = ({ fullScreen, isOpen, onClose, @@ -181,7 +185,14 @@ export const DataTablePageModal = ({ ); }; -DataTablePageModal.defaultProps = { +/** + * Only re-render this component when the isOpen prop changes. + */ +const propsAreEqual = ({ isOpen: prevIsOpen }, { isOpen: nextIsOpen }) => prevIsOpen === nextIsOpen; + +export const DataTablePageModal = React.memo(DataTablePageModalComponent, propsAreEqual); + +DataTablePageModalComponent.defaultProps = { fullScreen: false, modalKey: '', onSelect: null, @@ -189,7 +200,7 @@ DataTablePageModal.defaultProps = { modalObject: null, }; -DataTablePageModal.propTypes = { +DataTablePageModalComponent.propTypes = { modalObject: PropTypes.object, fullScreen: PropTypes.bool, isOpen: PropTypes.bool.isRequired, @@ -198,5 +209,3 @@ DataTablePageModal.propTypes = { onSelect: PropTypes.func, currentValue: PropTypes.any, }; - -export default DataTablePageModal; From 8ae831105195f1ccb993dd5c561a7a48f3ed20d6 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 17:02:24 +1200 Subject: [PATCH 03/14] Add useCallback for DataTable renderItem --- src/widgets/DataTable/DataTable.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/widgets/DataTable/DataTable.js b/src/widgets/DataTable/DataTable.js index b8ab5c690..16ca328dc 100644 --- a/src/widgets/DataTable/DataTable.js +++ b/src/widgets/DataTable/DataTable.js @@ -96,6 +96,11 @@ const DataTable = React.memo(({ renderRow, renderHeader, style, data, columns, . [numberOfEditableCells] ); + const renderItem = useCallback( + rowItem => renderRow(rowItem, focusNextCell, getCellRef, adjustToTop), + [renderRow] + ); + return ( {renderHeader && renderHeader()} @@ -105,7 +110,7 @@ const DataTable = React.memo(({ renderRow, renderHeader, style, data, columns, . data={data} keyboardShouldPersistTaps="always" style={style} - renderItem={rowItem => renderRow(rowItem, focusNextCell, getCellRef, adjustToTop)} + renderItem={renderItem} {...otherProps} /> From ad7a59b0990004386da0152cbc48e816f89e83ac Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 17:53:25 +1200 Subject: [PATCH 04/14] Add memoization to PageInfo --- src/widgets/PageInfo.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/widgets/PageInfo.js b/src/widgets/PageInfo.js index 40b590c56..7c46f4693 100644 --- a/src/widgets/PageInfo.js +++ b/src/widgets/PageInfo.js @@ -111,7 +111,7 @@ const renderInfoComponent = (isEditingDisabled, columnIndex, color, rowData, row * col1: row1 col2: row1 * col1: row2 col2: row2 */ -export const PageInfo = props => { +const PageInfoComponent = props => { const { columns, isEditingDisabled, titleColor, infoColor } = props; return ( @@ -148,16 +148,18 @@ export const PageInfo = props => { ); }; +export const PageInfo = React.memo(PageInfoComponent); + export default PageInfo; -PageInfo.propTypes = { +PageInfoComponent.propTypes = { columns: PropTypes.array.isRequired, isEditingDisabled: PropTypes.bool, titleColor: PropTypes.string, infoColor: PropTypes.string, }; -PageInfo.defaultProps = { +PageInfoComponent.defaultProps = { isEditingDisabled: false, infoColor: SUSSOL_ORANGE, titleColor: DARK_GREY, From 07cedf3cb674ce60b3f4588ffdf2e18b090efe46 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 18:00:33 +1200 Subject: [PATCH 05/14] Add update to all pages PageInfo usage --- src/pages/CustomerInvoicePage.js | 17 +++++++---------- src/pages/CustomerRequisitionPage.js | 15 +++++---------- src/pages/StocktakeEditPage.js | 15 +++++---------- src/pages/SupplierInvoicePage.js | 16 ++++++---------- src/pages/SupplierRequisitionPage.js | 16 ++++++---------- 5 files changed, 29 insertions(+), 50 deletions(-) diff --git a/src/pages/CustomerInvoicePage.js b/src/pages/CustomerInvoicePage.js index de369d4eb..1416df736 100644 --- a/src/pages/CustomerInvoicePage.js +++ b/src/pages/CustomerInvoicePage.js @@ -76,15 +76,11 @@ export const CustomerInvoicePage = ({ transaction, runWithLoadingIndicator, rout const onAddMasterList = () => runWithLoadingIndicator(() => dispatch(PageActions.addMasterListItems('Transaction'))); - const renderPageInfo = useCallback( - () => ( - - ), - [comment, theirRef, isFinalised] - ); + const pageInfoColumns = useCallback(getPageInfoColumns(pageObject, dispatch, PageActions), [ + comment, + theirRef, + isFinalised, + ]); const getAction = (colKey, propName) => { switch (colKey) { @@ -114,6 +110,7 @@ export const CustomerInvoicePage = ({ transaction, runWithLoadingIndicator, rout const renderRow = useCallback( listItem => { const { item, index } = listItem; + const rowKey = keyExtractor(item); return ( - {renderPageInfo()} + {renderButtons()} diff --git a/src/pages/CustomerRequisitionPage.js b/src/pages/CustomerRequisitionPage.js index 49c037b65..fb054e1d3 100644 --- a/src/pages/CustomerRequisitionPage.js +++ b/src/pages/CustomerRequisitionPage.js @@ -74,15 +74,10 @@ export const CustomerRequisitionPage = ({ requisition, runWithLoadingIndicator, const onSetSuppliedToSuggested = () => runWithLoadingIndicator(() => dispatch(PageActions.setSuppliedToSuggested())); - const renderPageInfo = useCallback( - () => ( - - ), - [comment, isFinalised] - ); + const pageInfoColumns = useCallback(getPageInfoColumns(pageObject, dispatch, PageActions), [ + comment, + isFinalised, + ]); const getAction = colKey => { switch (colKey) { @@ -176,7 +171,7 @@ export const CustomerRequisitionPage = ({ requisition, runWithLoadingIndicator, - {renderPageInfo()} + diff --git a/src/pages/StocktakeEditPage.js b/src/pages/StocktakeEditPage.js index 0bf20dc13..3289e5c9e 100644 --- a/src/pages/StocktakeEditPage.js +++ b/src/pages/StocktakeEditPage.js @@ -94,15 +94,10 @@ export const StocktakeEditPage = ({ const onManageStocktake = () => reduxDispatch(gotoStocktakeManagePage({ stocktake, stocktakeName: stocktake.name })); - const renderPageInfo = useCallback( - () => ( - - ), - [comment, isFinalised] - ); + const pageInfoColumns = useCallback(getPageInfoColumns(pageObject, dispatch, PageActions), [ + comment, + isFinalised, + ]); const getAction = (colKey, propName) => { switch (colKey) { @@ -190,7 +185,7 @@ export const StocktakeEditPage = ({ - {renderPageInfo()} + diff --git a/src/pages/SupplierInvoicePage.js b/src/pages/SupplierInvoicePage.js index 7c222236b..972a26af9 100644 --- a/src/pages/SupplierInvoicePage.js +++ b/src/pages/SupplierInvoicePage.js @@ -55,15 +55,11 @@ export const SupplierInvoicePage = ({ routeName, transaction }) => { const onConfirmDelete = () => dispatch(PageActions.deleteTransactionBatches()); const onCloseModal = () => dispatch(PageActions.closeModal()); - const renderPageInfo = useCallback( - () => ( - - ), - [comment, theirRef, isFinalised] - ); + const pageInfoColumns = useCallback(getPageInfoColumns(pageObject, dispatch, PageActions), [ + comment, + theirRef, + isFinalised, + ]); const getAction = (columnKey, propName) => { switch (columnKey) { @@ -148,7 +144,7 @@ export const SupplierInvoicePage = ({ routeName, transaction }) => { - {renderPageInfo()} + diff --git a/src/pages/SupplierRequisitionPage.js b/src/pages/SupplierRequisitionPage.js index a4c9b1320..37348d9c4 100644 --- a/src/pages/SupplierRequisitionPage.js +++ b/src/pages/SupplierRequisitionPage.js @@ -88,15 +88,11 @@ export const SupplierRequisitionPage = ({ requisition, runWithLoadingIndicator, const onAddFromMasterList = () => runWithLoadingIndicator(() => dispatch(PageActions.addMasterListItems('Requisition'))); - const renderPageInfo = useCallback( - () => ( - - ), - [comment, theirRef, isFinalised] - ); + const pageInfoColumns = useCallback(getPageInfoColumns(pageObject, dispatch, PageActions), [ + comment, + theirRef, + isFinalised, + ]); const getAction = (colKey, propName) => { switch (colKey) { @@ -279,7 +275,7 @@ export const SupplierRequisitionPage = ({ requisition, runWithLoadingIndicator, - {renderPageInfo()} + From ad2ded96048e73af7cf547f1b0dc17f6486ff174 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 18:04:23 +1200 Subject: [PATCH 06/14] Add memoization to getAction callback in all pages --- src/pages/CustomerInvoicePage.js | 4 ++-- src/pages/CustomerRequisitionPage.js | 4 ++-- src/pages/StocktakeEditPage.js | 4 ++-- src/pages/StocktakeManagePage.js | 4 ++-- src/pages/StocktakesPage.js | 4 ++-- src/pages/SupplierInvoicePage.js | 4 ++-- src/pages/SupplierInvoicesPage.js | 4 ++-- src/pages/SupplierRequisitionPage.js | 4 ++-- src/pages/SupplierRequisitionsPage.js | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/pages/CustomerInvoicePage.js b/src/pages/CustomerInvoicePage.js index 1416df736..41a2df7a4 100644 --- a/src/pages/CustomerInvoicePage.js +++ b/src/pages/CustomerInvoicePage.js @@ -82,7 +82,7 @@ export const CustomerInvoicePage = ({ transaction, runWithLoadingIndicator, rout isFinalised, ]); - const getAction = (colKey, propName) => { + const getAction = useCallback((colKey, propName) => { switch (colKey) { case 'totalQuantity': return PageActions.editTotalQuantity; @@ -92,7 +92,7 @@ export const CustomerInvoicePage = ({ transaction, runWithLoadingIndicator, rout default: return null; } - }; + }, []); const getModalOnSelect = () => { switch (modalKey) { diff --git a/src/pages/CustomerRequisitionPage.js b/src/pages/CustomerRequisitionPage.js index fb054e1d3..ab6db141a 100644 --- a/src/pages/CustomerRequisitionPage.js +++ b/src/pages/CustomerRequisitionPage.js @@ -79,14 +79,14 @@ export const CustomerRequisitionPage = ({ requisition, runWithLoadingIndicator, isFinalised, ]); - const getAction = colKey => { + const getAction = useCallback(colKey => { switch (colKey) { case 'suppliedQuantity': return PageActions.editSuppliedQuantity; default: return null; } - }; + }, []); const getModalOnSelect = () => { switch (modalKey) { diff --git a/src/pages/StocktakeEditPage.js b/src/pages/StocktakeEditPage.js index 3289e5c9e..31500997a 100644 --- a/src/pages/StocktakeEditPage.js +++ b/src/pages/StocktakeEditPage.js @@ -99,7 +99,7 @@ export const StocktakeEditPage = ({ isFinalised, ]); - const getAction = (colKey, propName) => { + const getAction = useCallback((colKey, propName) => { switch (colKey) { case 'countedTotalQuantity': return PageActions.editCountedQuantity; @@ -113,7 +113,7 @@ export const StocktakeEditPage = ({ default: return null; } - }; + }, []); const getModalOnSelect = () => { switch (modalKey) { diff --git a/src/pages/StocktakeManagePage.js b/src/pages/StocktakeManagePage.js index 73e3f17c0..7ca4a734e 100644 --- a/src/pages/StocktakeManagePage.js +++ b/src/pages/StocktakeManagePage.js @@ -50,7 +50,7 @@ export const StocktakeManagePage = ({ if (stocktake) dispatch(PageActions.selectItems(stocktake.itemsInStocktake)); }, []); - const getAction = (colKey, propName) => { + const getAction = useCallback((colKey, propName) => { switch (colKey) { case 'selected': if (propName === 'onCheckAction') return PageActions.selectRow; @@ -58,7 +58,7 @@ export const StocktakeManagePage = ({ default: return null; } - }; + }, []); const onFilterData = value => dispatch(PageActions.filterData(value)); const onNameChange = value => dispatch(PageActions.editName(value)); diff --git a/src/pages/StocktakesPage.js b/src/pages/StocktakesPage.js index 5e811ee1e..3d1a41033 100644 --- a/src/pages/StocktakesPage.js +++ b/src/pages/StocktakesPage.js @@ -63,7 +63,7 @@ export const StocktakesPage = ({ routeName, currentUser, dispatch: reduxDispatch return reduxDispatch(gotoStocktakeManagePage({ stocktakeName: '' })); }; - const getAction = (colKey, propName) => { + const getAction = useCallback((colKey, propName) => { switch (colKey) { case 'remove': if (propName === 'onCheckAction') return PageActions.selectRow; @@ -71,7 +71,7 @@ export const StocktakesPage = ({ routeName, currentUser, dispatch: reduxDispatch default: return null; } - }; + }, []); const getModalOnSelect = () => { switch (modalKey) { diff --git a/src/pages/SupplierInvoicePage.js b/src/pages/SupplierInvoicePage.js index 972a26af9..6301bc61d 100644 --- a/src/pages/SupplierInvoicePage.js +++ b/src/pages/SupplierInvoicePage.js @@ -61,7 +61,7 @@ export const SupplierInvoicePage = ({ routeName, transaction }) => { isFinalised, ]); - const getAction = (columnKey, propName) => { + const getAction = useCallback((columnKey, propName) => { switch (columnKey) { case 'totalQuantity': return PageActions.editTotalQuantity; @@ -73,7 +73,7 @@ export const SupplierInvoicePage = ({ routeName, transaction }) => { default: return null; } - }; + }, []); const getModalOnSelect = () => { switch (modalKey) { diff --git a/src/pages/SupplierInvoicesPage.js b/src/pages/SupplierInvoicesPage.js index 6fb66fb95..f951bfe65 100644 --- a/src/pages/SupplierInvoicesPage.js +++ b/src/pages/SupplierInvoicesPage.js @@ -64,7 +64,7 @@ export const SupplierInvoicesPage = ({ onCloseModal(); }; - const getAction = (colKey, propName) => { + const getAction = useCallback((colKey, propName) => { switch (colKey) { case 'remove': if (propName === 'onCheckAction') return PageActions.selectRow; @@ -72,7 +72,7 @@ export const SupplierInvoicesPage = ({ default: return null; } - }; + }, []); const getModalOnSelect = () => { switch (modalKey) { diff --git a/src/pages/SupplierRequisitionPage.js b/src/pages/SupplierRequisitionPage.js index 37348d9c4..41c94b74d 100644 --- a/src/pages/SupplierRequisitionPage.js +++ b/src/pages/SupplierRequisitionPage.js @@ -94,7 +94,7 @@ export const SupplierRequisitionPage = ({ requisition, runWithLoadingIndicator, isFinalised, ]); - const getAction = (colKey, propName) => { + const getAction = useCallback((colKey, propName) => { switch (colKey) { case 'requiredQuantity': return PageActions.editRequisitionItemRequiredQuantity; @@ -104,7 +104,7 @@ export const SupplierRequisitionPage = ({ requisition, runWithLoadingIndicator, default: return null; } - }; + }, []); const getModalOnSelect = () => { switch (modalKey) { diff --git a/src/pages/SupplierRequisitionsPage.js b/src/pages/SupplierRequisitionsPage.js index 489563b79..38fe03a33 100644 --- a/src/pages/SupplierRequisitionsPage.js +++ b/src/pages/SupplierRequisitionsPage.js @@ -90,7 +90,7 @@ export const SupplierRequisitionsPage = ({ reduxDispatch(createSupplierRequisition({ ...requisitionParameters, currentUser })); }; - const getAction = (colKey, propName) => { + const getAction = useCallback((colKey, propName) => { switch (colKey) { case 'remove': if (propName === 'onCheckAction') return PageActions.selectRow; @@ -98,7 +98,7 @@ export const SupplierRequisitionsPage = ({ default: return null; } - }; + }, []); const getModalOnSelect = () => { switch (modalKey) { From da6e8729ac3c8f722b21b3a8ce2c93c46b50570b Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 18:11:43 +1200 Subject: [PATCH 07/14] Add memoization of BottomConfirmModal --- src/widgets/modals/BottomConfirmModal.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/widgets/modals/BottomConfirmModal.js b/src/widgets/modals/BottomConfirmModal.js index 6f1009eb2..7b3ebee9e 100644 --- a/src/widgets/modals/BottomConfirmModal.js +++ b/src/widgets/modals/BottomConfirmModal.js @@ -14,7 +14,7 @@ import { modalStrings } from '../../localization'; import globalStyles, { SUSSOL_ORANGE } from '../../globalStyles'; -export const BottomConfirmModal = props => { +export const BottomConfirmModalComponent = props => { const { onCancel, onConfirm, @@ -44,9 +44,16 @@ export const BottomConfirmModal = props => { ); }; +/** + * Only re-render this component when isOpen prop changes. + */ +const propsAreEqual = ({ isOpen: prevIsOpen }, { isOpen: nextIsOpen }) => prevIsOpen === nextIsOpen; + +export const BottomConfirmModal = React.memo(BottomConfirmModalComponent, propsAreEqual); + export default BottomConfirmModal; -BottomConfirmModal.propTypes = { +BottomConfirmModalComponent.propTypes = { style: ViewPropTypes.style, isOpen: PropTypes.bool.isRequired, questionText: PropTypes.string.isRequired, @@ -55,7 +62,7 @@ BottomConfirmModal.propTypes = { cancelText: PropTypes.string, confirmText: PropTypes.string, }; -BottomConfirmModal.defaultProps = { +BottomConfirmModalComponent.defaultProps = { style: {}, cancelText: modalStrings.cancel, confirmText: modalStrings.confirm, From f996dd5ce08caa3e37d6689428744aff22004302 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 18:12:27 +1200 Subject: [PATCH 08/14] Add memoization to ItemDetails --- src/widgets/modals/ItemDetails.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/widgets/modals/ItemDetails.js b/src/widgets/modals/ItemDetails.js index 88cbebb3d..bb392ee9e 100644 --- a/src/widgets/modals/ItemDetails.js +++ b/src/widgets/modals/ItemDetails.js @@ -28,7 +28,7 @@ import { DARKER_GREY, SUSSOL_ORANGE } from '../../globalStyles'; * @param {Func} onClose Callback for closing the modal. * @param {Any} modalProps Any additional props for the modal component. */ -export const ItemDetails = ({ isOpen, item, onClose, ...modalProps }) => { +export const ItemDetailsComponent = ({ isOpen, item, onClose, ...modalProps }) => { const headers = { batch: 'Batch', expiryDate: 'Expiry', @@ -104,6 +104,21 @@ export const ItemDetails = ({ isOpen, item, onClose, ...modalProps }) => { ); }; +/** + * This component re-renders only when isOpen changes, or the underlying + * item object changes. + */ +const propsAreEqual = ( + { item: prevItem, isOpen: prevIsOpen }, + { item: nextItem, isOpen: nextIsOpen } +) => { + const itemsEqual = prevItem === nextItem; + const isOpenEqual = prevIsOpen === nextIsOpen; + return itemsEqual && isOpenEqual; +}; + +export const ItemDetails = React.memo(ItemDetailsComponent, propsAreEqual); + const localStyles = { scrollView: { height: 170, @@ -116,7 +131,7 @@ const localStyles = { headerRow: { flexDirection: 'row', justifyContent: 'flex-end', marginRight: 10 }, }; -ItemDetails.defaultProps = { +ItemDetailsComponent.defaultProps = { item: null, swipeToClose: false, backdropPressToClose: false, @@ -124,7 +139,7 @@ ItemDetails.defaultProps = { backdrop: false, }; -ItemDetails.propTypes = { +ItemDetailsComponent.propTypes = { item: PropTypes.object, onClose: PropTypes.func.isRequired, isOpen: PropTypes.bool.isRequired, From 1024ddda2a39591135ad54504c960b5f9cbb6247 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 18:17:14 +1200 Subject: [PATCH 09/14] Add checky change of icon --- src/widgets/icons.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/widgets/icons.js b/src/widgets/icons.js index dc1f5b580..3381c5218 100644 --- a/src/widgets/icons.js +++ b/src/widgets/icons.js @@ -10,6 +10,7 @@ import IonIcon from 'react-native-vector-icons/Ionicons'; import FAIcon from 'react-native-vector-icons/FontAwesome'; import EvilIcon from 'react-native-vector-icons/EvilIcons'; import EntypoIcon from 'react-native-vector-icons/Entypo'; +import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; import { SUSSOL_ORANGE, dataTableColors } from '../globalStyles'; @@ -25,9 +26,7 @@ export const UncheckedComponent = ( export const DisabledCheckedComponent = ( ); -export const DisabledUncheckedComponent = ( - -); +export const DisabledUncheckedComponent = ; export const MagnifyingGlass = ({ size, color }) => ( From 711d9e089cbf9f8171485c4d2f4a133c0d34aa24 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 19:36:31 +1200 Subject: [PATCH 10/14] Add white colour --- src/globalStyles/colors.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/globalStyles/colors.js b/src/globalStyles/colors.js index 4536e2652..5e0493554 100644 --- a/src/globalStyles/colors.js +++ b/src/globalStyles/colors.js @@ -18,3 +18,4 @@ export const SUSSOL_ORANGE = '#e95c30'; export const TRANSPARENT = 'rgba(0, 0, 0, 0)'; export const WARM_GREY = '#9b9b9b'; export const WARMER_GREY = '#a8aaac'; +export const WHITE = '#FFFFFF'; From 99e5985353d55a014a29535d62fe7c86f7c05a20 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 19:36:46 +1200 Subject: [PATCH 11/14] Add memoization of some icons --- src/widgets/icons.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/widgets/icons.js b/src/widgets/icons.js index 3381c5218..4fbd85128 100644 --- a/src/widgets/icons.js +++ b/src/widgets/icons.js @@ -12,11 +12,12 @@ import EvilIcon from 'react-native-vector-icons/EvilIcons'; import EntypoIcon from 'react-native-vector-icons/Entypo'; import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; -import { SUSSOL_ORANGE, dataTableColors } from '../globalStyles'; +import { SUSSOL_ORANGE, FINALISED_RED, dataTableColors } from '../globalStyles'; export const SortAscIcon = ; export const SortNeutralIcon = ; export const SortDescIcon = ; + export const CheckedComponent = ( ); @@ -28,18 +29,19 @@ export const DisabledCheckedComponent = ( ); export const DisabledUncheckedComponent = ; -export const MagnifyingGlass = ({ size, color }) => ( +export const MagnifyingGlass = React.memo(({ size, color }) => ( -); +)); + MagnifyingGlass.propTypes = { size: PropTypes.number, color: PropTypes.string }; MagnifyingGlass.defaultProps = { size: 40, color: SUSSOL_ORANGE }; -export const Cancel = ({ color, size }) => ; -Cancel.propTypes = { size: PropTypes.number, color: PropTypes.string }; -Cancel.defaultProps = { size: 40, color: SUSSOL_ORANGE }; -const closeIconStyle = { color: 'white' }; -export const CloseIcon = () => ; +export const Cancel = React.memo(() => ); -export const OpenModal = () => ; +export const CloseIcon = React.memo(() => ); + +export const Expand = React.memo(() => ( + +)); -export const Expand = () => ; +export const OpenModal = () => ; From ced76b7f97c6cebc76bffdc7ff6626ca11e52a05 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 19:37:03 +1200 Subject: [PATCH 12/14] Add remove props from icon in searchbar --- src/widgets/SearchBar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/SearchBar.js b/src/widgets/SearchBar.js index 384fe846e..4afba4905 100644 --- a/src/widgets/SearchBar.js +++ b/src/widgets/SearchBar.js @@ -90,7 +90,7 @@ export const SearchBarComponent = ({ /> {!!textValue && ( onChangeTextCallback('')}> - + )} From 38b33c2a47837d123c428535dd21eddafb12df69 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 19:37:39 +1200 Subject: [PATCH 13/14] Add memoized getActiomns in CustomerInvoicePage --- src/pages/CustomerInvoicesPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/CustomerInvoicesPage.js b/src/pages/CustomerInvoicesPage.js index b9697ff02..3a518c6fb 100644 --- a/src/pages/CustomerInvoicesPage.js +++ b/src/pages/CustomerInvoicesPage.js @@ -63,7 +63,7 @@ export const CustomerInvoicesPage = ({ onCloseModal(); }; - const getAction = (colKey, propName) => { + const getAction = useCallback((colKey, propName) => { switch (colKey) { case 'remove': if (propName === 'onCheckAction') return PageActions.selectRow; @@ -71,7 +71,7 @@ export const CustomerInvoicesPage = ({ default: return null; } - }; + }, []); const getModalOnSelect = () => { switch (modalKey) { From 0dbcdafe0638305a6c7b60aedbcd9e0b0f76c31a Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 21 Sep 2019 22:41:02 +1200 Subject: [PATCH 14/14] Add update to icons and CheckableCell --- src/widgets/DataTable/CheckableCell.js | 17 +++++++---------- src/widgets/icons.js | 15 +++++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/widgets/DataTable/CheckableCell.js b/src/widgets/DataTable/CheckableCell.js index 9a4b5cbae..d923459ce 100644 --- a/src/widgets/DataTable/CheckableCell.js +++ b/src/widgets/DataTable/CheckableCell.js @@ -48,12 +48,9 @@ const CheckableCell = React.memo( const onPressAction = isChecked ? onUncheckAction : onCheckAction; - const renderCheck = () => { - if (isDisabled) { - return isChecked ? DisabledCheckedComponent : DisabledUncheckedComponent; - } - return isChecked ? CheckedComponent : UncheckedComponent; - }; + const renderCheck = isChecked + ? (isDisabled && DisabledCheckedComponent) || CheckedComponent + : (isDisabled && DisabledUncheckedComponent) || UncheckedComponent; return ( ; export const SortDescIcon = ; -export const CheckedComponent = ( +export const CheckedComponent = () => ( ); -export const UncheckedComponent = ( + +export const UncheckedComponent = () => ( ); -export const DisabledCheckedComponent = ( + +export const DisabledCheckedComponent = () => ( ); -export const DisabledUncheckedComponent = ; + +export const DisabledUncheckedComponent = () => ; + +export const OpenModal = () => ; export const MagnifyingGlass = React.memo(({ size, color }) => ( @@ -43,5 +48,3 @@ export const CloseIcon = React.memo(() => ( )); - -export const OpenModal = () => ;