perf: use useSelector with granular approach in registration component to minimize rendrening

This commit is contained in:
mubbsharanwar
2024-03-26 15:09:54 +05:00
committed by Mubbshar Anwar
parent 2d37b8b0bf
commit cd8474465b
5 changed files with 60 additions and 64 deletions

View File

@@ -37,10 +37,8 @@ const EmailField = (props) => {
confirmEmailValue,
} = props;
const {
registrationFormData: backedUpFormData,
validationApiRateLimited,
} = useSelector(state => state.register);
const backedUpFormData = useSelector(state => state.register.registrationFormData);
const validationApiRateLimited = useSelector(state => state.register.validationApiRateLimited);
const [emailSuggestion, setEmailSuggestion] = useState({ ...backedUpFormData?.emailSuggestion });

View File

@@ -41,7 +41,8 @@ const UsernameField = (props) => {
let className = '';
let suggestedUsernameDiv = null;
let iconButton = null;
const { usernameSuggestions, validationApiRateLimited } = useSelector(state => state.register);
const usernameSuggestions = useSelector(state => state.register.usernameSuggestions);
const validationApiRateLimited = useSelector(state => state.register.validationApiRateLimited);
/**
* We need to remove the placeholder from the field, adding a space will do that.

View File

@@ -25,8 +25,9 @@ import {
FORM_SUBMISSION_ERROR,
TPA_AUTHENTICATION_FAILURE,
} from './data/constants';
import getBackendValidations from './data/selectors';
import {
getBackendValidations, isFormValid, prepareRegistrationPayload,
isFormValid, prepareRegistrationPayload,
} from './data/utils';
import messages from './messages';
import { EmailField, NameField, UsernameField } from './RegistrationFields';
@@ -65,38 +66,26 @@ const RegistrationPage = (props) => {
institutionLogin,
} = props;
const {
registrationFormData: backedUpFormData,
registrationError,
registrationError: {
errorCode: registrationErrorCode,
} = {},
registrationResult,
shouldBackupState,
userPipelineDataLoaded,
submitState,
validations,
} = useSelector(state => state.register);
const backedUpFormData = useSelector(state => state.register.registrationFormData);
const registrationError = useSelector(state => state.register.registrationError);
const registrationErrorCode = registrationError?.errorCode;
const registrationResult = useSelector(state => state.register.registrationResult);
const shouldBackupState = useSelector(state => state.register.shouldBackupState);
const userPipelineDataLoaded = useSelector(state => state.register.userPipelineDataLoaded);
const submitState = useSelector(state => state.register.submitState);
const {
fieldDescriptions,
optionalFields,
thirdPartyAuthApiStatus,
thirdPartyAuthContext,
thirdPartyAuthContext: {
autoSubmitRegForm,
errorMessage: thirdPartyAuthErrorMessage,
finishAuthUrl,
currentProvider,
providers,
secondaryProviders,
pipelineUserDetails,
},
} = useSelector(state => state.commonComponents);
const fieldDescriptions = useSelector(state => state.commonComponents.fieldDescriptions);
const optionalFields = useSelector(state => state.commonComponents.optionalFields);
const thirdPartyAuthApiStatus = useSelector(state => state.commonComponents.thirdPartyAuthApiStatus);
const autoSubmitRegForm = useSelector(state => state.commonComponents.thirdPartyAuthContext.autoSubmitRegForm);
const thirdPartyAuthErrorMessage = useSelector(state => state.commonComponents.thirdPartyAuthContext.errorMessage);
const finishAuthUrl = useSelector(state => state.commonComponents.thirdPartyAuthContext.finishAuthUrl);
const currentProvider = useSelector(state => state.commonComponents.thirdPartyAuthContext.currentProvider);
const providers = useSelector(state => state.commonComponents.thirdPartyAuthContext.providers);
const secondaryProviders = useSelector(state => state.commonComponents.thirdPartyAuthContext.secondaryProviders);
const pipelineUserDetails = useSelector(state => state.commonComponents.thirdPartyAuthContext.pipelineUserDetails);
const backendValidations = useMemo(
() => getBackendValidations(registrationError, validations), [registrationError, validations],
);
const backendValidations = useSelector(getBackendValidations);
const queryParams = useMemo(() => getAllPossibleQueryParams(), []);
const tpaHint = useMemo(() => getTpaHint(), []);
@@ -130,7 +119,9 @@ const RegistrationPage = (props) => {
}
}
}, [ // eslint-disable-line react-hooks/exhaustive-deps
thirdPartyAuthContext,
thirdPartyAuthApiStatus,
thirdPartyAuthErrorMessage,
pipelineUserDetails,
userPipelineDataLoaded,
]);

View File

@@ -0,0 +1,33 @@
import { createSelector } from 'reselect';
/**
* Selector for backend validations which processes the api output and generates a
* key value dict for field errors.
* @returns {{username: string}|{name: string}|*|{}|null}
*/
const getRegistrationError = state => state.register.registrationError;
const getValidations = state => state.register.validations;
const getBackendValidations = createSelector(
[getRegistrationError, getValidations],
(registrationError, validations) => {
if (validations) {
return validations.validationDecisions;
}
if (Object.keys(registrationError).length > 0) {
const fields = Object.keys(registrationError).filter(
(fieldName) => !(fieldName in ['errorCode', 'usernameSuggestions']),
);
const validationDecisions = {};
fields.forEach(field => {
validationDecisions[field] = registrationError[field][0].userMessage || '';
});
return validationDecisions;
}
return null;
});
export default getBackendValidations;

View File

@@ -132,30 +132,3 @@ export const prepareRegistrationPayload = (
payload = { ...payload, ...queryParams };
return payload;
};
/**
* A helper for backend validations selector. It processes the api output and generates a
* key value dict for field errors.
* @param registrationError
* @param validations
* @returns {{username: string}|{name: string}|*|{}|null}
*/
export const getBackendValidations = (registrationError, validations) => {
if (validations) {
return validations.validationDecisions;
}
if (Object.keys(registrationError).length > 0) {
const fields = Object.keys(registrationError).filter(
(fieldName) => !(fieldName in ['errorCode', 'usernameSuggestions']),
);
const validationDecisions = {};
fields.forEach(field => {
validationDecisions[field] = registrationError[field][0].userMessage || '';
});
return validationDecisions;
}
return null;
};