From 1a09dcca3f0371096d5ddbd066acf72a794ecd30 Mon Sep 17 00:00:00 2001 From: Daniel Stefan Date: Fri, 15 Jul 2022 15:09:41 +0300 Subject: [PATCH] feat: improve app performance --- src/components/forms/ProjectCreateModal.js | 58 ++++++++++--------- src/components/forms/ProjectEditModal.js | 58 ++++++++++--------- src/components/forms/ProjectEstimationForm.js | 7 ++- src/components/forms/ProjectIssuanceForm.js | 7 ++- src/components/forms/ProjectLabelForm.js | 7 ++- src/components/forms/ProjectLocationForm.js | 7 ++- src/components/forms/ProjectRatingForm.js | 7 ++- .../forms/ProjectRelatedProjectForm.js | 7 ++- src/components/forms/SubscriptionModal.js | 19 +++++- src/components/forms/UnitCreateModal.js | 43 +++++++------- src/components/forms/UnitEditModal.js | 51 +++++++++------- src/components/forms/UnitIssuanceForm.js | 51 ++++++++-------- src/components/layout/ConditionalWrap.js | 5 -- src/components/layout/VerticalSpacer.js | 13 ----- src/components/layout/index.js | 2 - 15 files changed, 189 insertions(+), 153 deletions(-) delete mode 100644 src/components/layout/ConditionalWrap.js delete mode 100644 src/components/layout/VerticalSpacer.js diff --git a/src/components/forms/ProjectCreateModal.js b/src/components/forms/ProjectCreateModal.js index 81f13c94..a1e63597 100644 --- a/src/components/forms/ProjectCreateModal.js +++ b/src/components/forms/ProjectCreateModal.js @@ -1,5 +1,5 @@ import _ from 'lodash'; -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Stepper, Step, StepLabel } from '@mui/material'; import { useIntl } from 'react-intl'; @@ -103,36 +103,42 @@ const ProjectCreateModal = ({ onClose, modalSizeAndPosition }) => { const { notification, showProgressOverlay: apiResponseIsPending } = useSelector(state => state.app); - const stepperStepsTranslationIds = [ - 'project', - 'issuances', - 'project-locations', - 'estimations', - 'labels', - 'ratings', - 'co-benefits', - 'related-projects', - ]; + const stepperStepsTranslationIds = useMemo( + () => [ + 'project', + 'issuances', + 'project-locations', + 'estimations', + 'labels', + 'ratings', + 'co-benefits', + 'related-projects', + ], + [], + ); - const onChangeStepTo = async ({ formik, desiredStep = null }) => { - const errors = await formik.validateForm(); + const onChangeStepTo = useCallback( + async ({ formik, desiredStep = null }) => { + const errors = await formik.validateForm(); - // manually setting touched for error fields so errors are displayed - formik.setTouched(setNestedObjectValues(errors, true)); + // manually setting touched for error fields so errors are displayed + formik.setTouched(setNestedObjectValues(errors, true)); - const isProjectValid = _.isEmpty(errors); + const isProjectValid = _.isEmpty(errors); - if (isProjectValid) { - if ( - desiredStep >= stepperStepsTranslationIds.length && - !apiResponseIsPending - ) { - formik.submitForm(); - } else { - setTabValue(desiredStep); + if (isProjectValid) { + if ( + desiredStep >= stepperStepsTranslationIds.length && + !apiResponseIsPending + ) { + formik.submitForm(); + } else { + setTabValue(desiredStep); + } } - } - }; + }, + [setTabValue, apiResponseIsPending], + ); // if project was successfully created, close modal const projectWasSuccessfullyCreated = diff --git a/src/components/forms/ProjectEditModal.js b/src/components/forms/ProjectEditModal.js index e77841e5..f5bf41ef 100644 --- a/src/components/forms/ProjectEditModal.js +++ b/src/components/forms/ProjectEditModal.js @@ -1,5 +1,5 @@ import _ from 'lodash'; -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Stepper, Step, StepLabel } from '@mui/material'; import { useIntl } from 'react-intl'; @@ -57,36 +57,42 @@ const ProjectEditModal = ({ setProject(formattedProjectData); }, [projectToBeEdited]); - const stepperStepsTranslationIds = [ - 'project', - 'issuances', - 'project-locations', - 'estimations', - 'labels', - 'ratings', - 'co-benefits', - 'related-projects', - ]; + const stepperStepsTranslationIds = useMemo( + () => [ + 'project', + 'issuances', + 'project-locations', + 'estimations', + 'labels', + 'ratings', + 'co-benefits', + 'related-projects', + ], + [], + ); - const onChangeStepTo = async ({ formik, desiredStep = null }) => { - const errors = await formik.validateForm(); + const onChangeStepTo = useCallback( + async ({ formik, desiredStep = null }) => { + const errors = await formik.validateForm(); - // manually setting touched for error fields so errors are displayed - formik.setTouched(setNestedObjectValues(errors, true)); + // manually setting touched for error fields so errors are displayed + formik.setTouched(setNestedObjectValues(errors, true)); - const isProjectValid = _.isEmpty(errors); + const isProjectValid = _.isEmpty(errors); - if (isProjectValid) { - if ( - desiredStep >= stepperStepsTranslationIds.length && - !apiResponseIsPending - ) { - formik.submitForm(); - } else { - setTabValue(desiredStep); + if (isProjectValid) { + if ( + desiredStep >= stepperStepsTranslationIds.length && + !apiResponseIsPending + ) { + formik.submitForm(); + } else { + setTabValue(desiredStep); + } } - } - }; + }, + [setTabValue, apiResponseIsPending], + ); // if project was successfully edited, close modal const projectWasSuccessfullyEdited = diff --git a/src/components/forms/ProjectEstimationForm.js b/src/components/forms/ProjectEstimationForm.js index 510f20e8..1a67082b 100644 --- a/src/components/forms/ProjectEstimationForm.js +++ b/src/components/forms/ProjectEstimationForm.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import { useIntl, FormattedMessage } from 'react-intl'; import { @@ -32,7 +32,10 @@ const ProjectEstimationForm = ({ handleBlur, }) => { const intl = useIntl(); - const getFieldName = fieldName => `${name}[${index}].${fieldName}`; + const getFieldName = useCallback( + fieldName => `${name}[${index}].${fieldName}`, + [name, index], + ); return ( diff --git a/src/components/forms/ProjectIssuanceForm.js b/src/components/forms/ProjectIssuanceForm.js index bfe55c9b..bffc8eec 100644 --- a/src/components/forms/ProjectIssuanceForm.js +++ b/src/components/forms/ProjectIssuanceForm.js @@ -1,4 +1,4 @@ -import React, { memo } from 'react'; +import React, { memo, useCallback } from 'react'; import { useIntl, FormattedMessage } from 'react-intl'; import { @@ -26,7 +26,10 @@ import { const ProjectIssuanceForm = memo( ({ index, name, errors, touched, value, setFieldValue, handleBlur }) => { const intl = useIntl(); - const getFieldName = fieldName => `${name}[${index}].${fieldName}`; + const getFieldName = useCallback( + fieldName => `${name}[${index}].${fieldName}`, + [name, index], + ); const areFieldsDisabled = Boolean(value.id); return ( diff --git a/src/components/forms/ProjectLabelForm.js b/src/components/forms/ProjectLabelForm.js index 1e03d55b..5b6be041 100644 --- a/src/components/forms/ProjectLabelForm.js +++ b/src/components/forms/ProjectLabelForm.js @@ -1,4 +1,4 @@ -import React, { memo } from 'react'; +import React, { memo, useCallback } from 'react'; import { useSelector } from 'react-redux'; import { useIntl, FormattedMessage } from 'react-intl'; @@ -35,7 +35,10 @@ const ProjectLabelForm = memo( ({ index, name, errors, touched, value, setFieldValue, handleBlur }) => { const intl = useIntl(); const { pickLists } = useSelector(store => store.climateWarehouse); - const getFieldName = fieldName => `${name}[${index}].${fieldName}`; + const getFieldName = useCallback( + fieldName => `${name}[${index}].${fieldName}`, + [name, index], + ); const areFieldsDisabled = Boolean(value.id); return ( diff --git a/src/components/forms/ProjectLocationForm.js b/src/components/forms/ProjectLocationForm.js index 8111cdbf..2b79b6f6 100644 --- a/src/components/forms/ProjectLocationForm.js +++ b/src/components/forms/ProjectLocationForm.js @@ -1,4 +1,4 @@ -import React, { memo } from 'react'; +import React, { memo, useCallback } from 'react'; import { useSelector } from 'react-redux'; import { FormattedMessage, useIntl } from 'react-intl'; @@ -30,7 +30,10 @@ import { const ProjectLocationForm = memo( ({ index, name, errors, touched, value, setFieldValue, handleBlur }) => { const intl = useIntl(); - const getFieldName = fieldName => `${name}[${index}].${fieldName}`; + const getFieldName = useCallback( + fieldName => `${name}[${index}].${fieldName}`, + [index, name], + ); const { pickLists } = useSelector(store => store.climateWarehouse); return ( diff --git a/src/components/forms/ProjectRatingForm.js b/src/components/forms/ProjectRatingForm.js index b0aff5e9..15b85816 100644 --- a/src/components/forms/ProjectRatingForm.js +++ b/src/components/forms/ProjectRatingForm.js @@ -1,4 +1,4 @@ -import React, { memo } from 'react'; +import React, { memo, useCallback } from 'react'; import { useIntl, FormattedMessage } from 'react-intl'; import { useSelector } from 'react-redux'; import { FormikError } from '../form/FormikError'; @@ -32,7 +32,10 @@ const ProjectRatingForm = memo( ({ index, name, errors, touched, value, setFieldValue, handleBlur }) => { const intl = useIntl(); const { pickLists } = useSelector(store => store.climateWarehouse); - const getFieldName = fieldName => `${name}[${index}].${fieldName}`; + const getFieldName = useCallback( + fieldName => `${name}[${index}].${fieldName}`, + [index, name], + ); return ( diff --git a/src/components/forms/ProjectRelatedProjectForm.js b/src/components/forms/ProjectRelatedProjectForm.js index dc258c77..e45dab74 100644 --- a/src/components/forms/ProjectRelatedProjectForm.js +++ b/src/components/forms/ProjectRelatedProjectForm.js @@ -1,4 +1,4 @@ -import React, { memo } from 'react'; +import React, { memo, useCallback } from 'react'; import { useIntl, FormattedMessage } from 'react-intl'; import { FormikError } from '../form/FormikError'; @@ -23,7 +23,10 @@ import { const ProjectRelatedProjectForm = memo( ({ index, name, errors, touched, value, setFieldValue, handleBlur }) => { const intl = useIntl(); - const getFieldName = fieldName => `${name}[${index}].${fieldName}`; + const getFieldName = useCallback( + fieldName => `${name}[${index}].${fieldName}`, + [name, index], + ); return ( diff --git a/src/components/forms/SubscriptionModal.js b/src/components/forms/SubscriptionModal.js index e79e0270..dd581132 100644 --- a/src/components/forms/SubscriptionModal.js +++ b/src/components/forms/SubscriptionModal.js @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useIntl, FormattedMessage } from 'react-intl'; import { useDispatch, useSelector } from 'react-redux'; import styled from 'styled-components'; @@ -81,7 +81,7 @@ const SubscriptionModal = ({ onClose }) => { return false; }, [orgUid]); - const submitCustomOrganization = () => { + const submitCustomOrganization = useCallback(() => { if (!isValidationOn) { setIsValidation(true); } @@ -100,7 +100,20 @@ const SubscriptionModal = ({ onClose }) => { } else { setTimeout(() => setIsValidation(false), 3000); } - }; + }, [ + isValidationOn, + setIsValidation, + isOrgUidValid, + isIpValid, + isPortValid, + isUserAlreadySubscribedToOrgUid, + orgUid, + setOrgUid, + ip, + setIp, + port, + setPort, + ]); return ( <> diff --git a/src/components/forms/UnitCreateModal.js b/src/components/forms/UnitCreateModal.js index 73912b19..b35e3d27 100644 --- a/src/components/forms/UnitCreateModal.js +++ b/src/components/forms/UnitCreateModal.js @@ -83,32 +83,35 @@ const UnitCreateModal = ({ onClose, modalSizeAndPosition }) => { } }, []); - const onChangeStepTo = useCallback(async ({ formik, desiredStep = null }) => { - const errors = await formik.validateForm(); + const onChangeStepTo = useCallback( + async ({ formik, desiredStep = null }) => { + const errors = await formik.validateForm(); - // manually setting touched for error fields so errors are displayed - formik.setTouched(setNestedObjectValues(errors, true)); + // manually setting touched for error fields so errors are displayed + formik.setTouched(setNestedObjectValues(errors, true)); - const isUnitValid = _.isEmpty(errors); + const isUnitValid = _.isEmpty(errors); - const isIssuanceSelected = - desiredStep > 1 ? !_.isEmpty(formik.values?.issuance) : true; + const isIssuanceSelected = + desiredStep > 1 ? !_.isEmpty(formik.values?.issuance) : true; - const isProjectSelected = Boolean( - localStorage.getItem('unitSelectedWarehouseProjectId'), - ); + const isProjectSelected = Boolean( + localStorage.getItem('unitSelectedWarehouseProjectId'), + ); - if (isUnitValid && isProjectSelected && isIssuanceSelected) { - if ( - desiredStep >= stepperStepsTranslationIds.length && - !apiResponseIsPending - ) { - formik.submitForm(); - } else { - setTabValue(desiredStep); + if (isUnitValid && isProjectSelected && isIssuanceSelected) { + if ( + desiredStep >= stepperStepsTranslationIds.length && + !apiResponseIsPending + ) { + formik.submitForm(); + } else { + setTabValue(desiredStep); + } } - } - }, []); + }, + [setTabValue, apiResponseIsPending], + ); // if unit was successfully created, close modal const unitWasSuccessfullyCreated = diff --git a/src/components/forms/UnitEditModal.js b/src/components/forms/UnitEditModal.js index 1723f123..df47b4d1 100644 --- a/src/components/forms/UnitEditModal.js +++ b/src/components/forms/UnitEditModal.js @@ -1,5 +1,5 @@ import _ from 'lodash'; -import React, { useState, useEffect, useCallback } from 'react'; +import React, { useState, useEffect, useCallback, useMemo } from 'react'; import styled from 'styled-components'; import { useDispatch, useSelector } from 'react-redux'; import { Stepper, Step, StepLabel } from '@mui/material'; @@ -75,34 +75,41 @@ const UnitEditModal = ({ onClose, record, modalSizeAndPosition }) => { } }, []); - const stepperStepsTranslationIds = ['unit', 'issuance', 'labels']; + const stepperStepsTranslationIds = useMemo(() => [ + 'unit', + 'issuance', + 'labels', + ]); - const onChangeStep = useCallback(async ({ formik, desiredStep = null }) => { - const errors = await formik.validateForm(); + const onChangeStep = useCallback( + async ({ formik, desiredStep = null }) => { + const errors = await formik.validateForm(); - // manually setting touched for error fields so errors are displayed - formik.setTouched(setNestedObjectValues(errors, true)); + // manually setting touched for error fields so errors are displayed + formik.setTouched(setNestedObjectValues(errors, true)); - const isUnitValid = _.isEmpty(errors); + const isUnitValid = _.isEmpty(errors); - const isIssuanceSelected = - desiredStep > 1 ? !_.isEmpty(formik.values?.issuance) : true; + const isIssuanceSelected = + desiredStep > 1 ? !_.isEmpty(formik.values?.issuance) : true; - const isProjectSelected = Boolean( - localStorage.getItem('unitSelectedWarehouseProjectId'), - ); + const isProjectSelected = Boolean( + localStorage.getItem('unitSelectedWarehouseProjectId'), + ); - if (isUnitValid && isProjectSelected && isIssuanceSelected) { - if ( - desiredStep >= stepperStepsTranslationIds.length && - !apiResponseIsPending - ) { - formik.submitForm(); - } else { - setTabValue(desiredStep); + if (isUnitValid && isProjectSelected && isIssuanceSelected) { + if ( + desiredStep >= stepperStepsTranslationIds.length && + !apiResponseIsPending + ) { + formik.submitForm(); + } else { + setTabValue(desiredStep); + } } - } - }, []); + }, + [setTabValue, apiResponseIsPending], + ); // if unit was successfully edited, close modal const unitWasSuccessfullyEdited = diff --git a/src/components/forms/UnitIssuanceForm.js b/src/components/forms/UnitIssuanceForm.js index b0e3b90e..84504cf8 100644 --- a/src/components/forms/UnitIssuanceForm.js +++ b/src/components/forms/UnitIssuanceForm.js @@ -91,27 +91,17 @@ const UnitIssuanceForm = () => { return []; }, [issuances, selectedWarehouseProjectId]); - const updateIssuanceById = id => { - const issuanceIsAvailable = issuances?.some( - issuance => issuance?.id === id, - ); - const selectedIssuance = - issuanceIsAvailable && - issuances.filter(issuance => issuance?.id === id)[0]; + const updateIssuanceById = useCallback( + id => { + const issuanceIsAvailable = issuances?.some( + issuance => issuance?.id === id, + ); + const selectedIssuance = + issuanceIsAvailable && + issuances.filter(issuance => issuance?.id === id)[0]; - if (selectedIssuance) { - const { - endDate, - startDate, - verificationApproach, - verificationBody, - verificationReportDate, - id, - warehouseProjectId, - } = selectedIssuance; - setValues({ - ...values, - issuance: { + if (selectedIssuance) { + const { endDate, startDate, verificationApproach, @@ -119,10 +109,23 @@ const UnitIssuanceForm = () => { verificationReportDate, id, warehouseProjectId, - }, - }); - } - }; + } = selectedIssuance; + setValues({ + ...values, + issuance: { + endDate, + startDate, + verificationApproach, + verificationBody, + verificationReportDate, + id, + warehouseProjectId, + }, + }); + } + }, + [issuances, values, setValues], + ); return ( diff --git a/src/components/layout/ConditionalWrap.js b/src/components/layout/ConditionalWrap.js deleted file mode 100644 index 321cea03..00000000 --- a/src/components/layout/ConditionalWrap.js +++ /dev/null @@ -1,5 +0,0 @@ -function ConditionalWrap({condition, wrap, children}) { - return condition ? wrap(children) : children; -} - -export {ConditionalWrap}; diff --git a/src/components/layout/VerticalSpacer.js b/src/components/layout/VerticalSpacer.js deleted file mode 100644 index 13881293..00000000 --- a/src/components/layout/VerticalSpacer.js +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; -import styled from 'styled-components'; - -const Container = styled('div')` - height: ${props => props.size}px; - width: 100%; -`; - -const VerticalSpacer = ({children, size}) => ( - {children} -); - -export {VerticalSpacer}; diff --git a/src/components/layout/index.js b/src/components/layout/index.js index c152d80e..7504fff4 100644 --- a/src/components/layout/index.js +++ b/src/components/layout/index.js @@ -1,6 +1,4 @@ export * from './IndeterminateProgressOverlay'; -export * from './ConditionalWrap'; -export * from './VerticalSpacer'; export * from './Dashboard'; export * from './TabPanel'; export * from './Tabs';