perf: use useSelector with granular approach in registration component to minimize rendrening
This commit is contained in:
committed by
Mubbshar Anwar
parent
2d37b8b0bf
commit
cd8474465b
@@ -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 });
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
]);
|
||||
|
||||
|
||||
33
src/register/data/selectors.js
Normal file
33
src/register/data/selectors.js
Normal 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;
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user