I have the following React code,
const useDynamicReplaceVariable = ({ label, formikValues, fieldsTypes }) => {
const { locale } = useTranslationState();
const formattedLabel = useMemo(() => {
const variablesRegex = /\?([\w-]+)\?/g;
let labelResult = label;
if (variablesRegex.test(label)) {
labelResult = ' ';
if (Object.keys(formikValues).length > 0) {
labelResult = label.replace(variablesRegex, (_, ...[variable]) => {
const type = fieldsTypes[variable];
// Set undefined or null to empty
let variableValue = (formikValues[variable] === undefined || formikValues[variable] == null) ? '' : formikValues[variable];
if (variableValue && [DesignerDdTypes.DatePicker, DesignerDdTypes.DatetimePicker].includes(type)) {
variableValue = dateToString(variableValue, locale, type === DesignerDdTypes.DatetimePicker);
}
return variableValue;
});
}
}
return labelResult;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [label, JSON.stringify(formikValues)]);
return { formattedLabel };
};
I can't understand the line labelResult = label.replace(variablesRegex, (_, ...[variable]), when no variable is defined, how come spread syntax is applied over it?
...[variable] is a shorthand for
function someFunction(...args) {
const [variable] = args
}
someFunction(1, 2, 3, 4, 5)
function someFunction(arg1, ...args) {
console.log('arg1', arg1)
console.log('args', args)
const [variable] = args
console.log('variable', variable)
}
someFunction(1, 2, 3, 4, 5)
function someFunction(arg1, ...[variable]) {
console.log('arg1', arg1)
console.log('variable', variable)
}
Related
I want to lookup for a key on an object, but if the key does't exist, it must return null, is it possible in JavaScript?
const d = {
A: () => { return 'A' },
B: () => { return 'B' },
C: () => { return 'C' },
}
const key = 'Z'
const func = d[key] // HERE
console.log(func)
You can use or: ||
or the newer optional chaining and Nullish coalescing operator
NOTE: the arrow function suggested by Máté Wiszt has to be wrapped in () or it will give an error
const d = {
A: () => { return 'A' },
B: () => { return 'B' },
C: () => { return 'C' },
}
let key = 'A'
let func = d[key] || null;
console.log(func && func())
key = 'Z'
func = d[key] || null
console.log(func && func())
func = d[key] || function() { return null };
console.log(func && func())
func = d?.[key] ?? (() => null); // arrow has to be wrapped
console.log(func())
// undefined key
let key1;
console.log({key1})
func = d?.[key1] ?? (() => null); // arrow has to be wrapped
console.log("Using undefined key1:",func())
You can do:
const func = d[key] || () => null;
In this case you can call func safely.
It will be better to use hasOwnProperty to check wheather that property exist in the object d or not.
const d1 = {
A: () => { return "A"; },
B: () => { return "B"; },
C: () => { return "C"; },
Z: undefined,
};
const d2 = {
A: () => { return "A"; },
B: () => { return "B"; },
C: () => { return "C"; },
};
const key = "Z";
function getValue(obj, key) {
return obj.hasOwnProperty(key) ? obj[key] : null;
}
const func1 = getValue(d1, key);
console.log(func1);
const func2 = d1[key] || null; // Shouldn't use
console.log(func2);
const func3 = d1[key] ?? null; // Shouldn't use
console.log(func3);
this is the first function , i have this function getAffliateCodesAsync() my requirement is to call this method from inside other function (function -2 >> generateCriBodyWithCreParameter(..))
and pass the returning value of >>(function-1) getAffliateCodesAsync(), into the third function and use that value in (function -3) checkLessorMagnitudeCode(..) and use the returning value of function-2 in function-3 at place where codeList is used, Please help
//function-1.
async function getAffliateCodesAsync(){
console.debug("==AFFILIATE_CODES==");
const ApplicationParameter = loopback.getModel('ApplicationParameter');
const applicationParamFieldValue = await ApplicationParameter.find({
where: {
fieldName: 'AFFILIATE_CODES'
},
fields: ['fieldValue']
});
return (applicationParamFieldValue.length)? applicationParamFieldValue.map(entity => String(entity['fieldValue'])):[];
}
//2.function-2
const generateCriBodyWithCreParameter = (positions, lotNumber, cutOffDate) => {
const CreParameter = loopback.getModel('CreParameter');
let creId = 1;
const positionData = [];
const content = [];
return CreParameter.find()
.then((creParameterList) => {
const promises = positions.map((position) => {
const cutOffDatePreviousMonth = getCutOffDatePreviousMonth(position.accountingDate);
return positionNativeProvider.getPositionInformationForPreviousCutOffDateForCriApf(
position, cutOffDatePreviousMonth)
.then((positionRetrieved) => {
const positionLowerCase = _.mapKeys(position, (value, key) => _.toLower(key));
const creParameters = _.filter(creParameterList, {
flowType: 'MI',
event: 'POSITION',
liabilityAmortizationMethod: position.liabilityAmortizationMethod
});
for (const creParameter of creParameters) {
const atollAmountValue = getAtollAmountValue(positionLowerCase, creParameter);
if (atollAmountValue && matchSigns(atollAmountValue, creParameter.amountSign)) {
const lineGenerated = checkContractLegalStatusForCri(position, creParameter,
atollAmountValue, content, creId, lotNumber, cutOffDate, positionRetrieved);
//No Line is generated in this case so the creId must not incremente
if (lineGenerated !== -1) {
positionData.push({
positionId: position.id,
creId
});
creId++;
}
}
}
});
});
return Promise.all(promises)
.then(() => {
return {
contentCreBody: content.join('\n'),
positionData
};
});
});
};
//function -3
const checkLessorMagnitudeCode = (lessorMagnitudeCode,codeList=[]) => {
if (!lessorMagnitudeCode) return false;
if (_.size(lessorMagnitudeCode) === 5 &&
(_.startsWith(lessorMagnitudeCode, 'S') || _.startsWith(lessorMagnitudeCode, 'T'))
&& codeList.includes(lessorMagnitudeCode)) {
return true;
}
return false;
};
//above codelist where I want to use the returning value
I have the below recursion function:
const getDiff = (object, base) => {
const changes = (object, base, path = "") => {
return _.transform(object, function(result, value, key) {
if (!_.isEqual(value, base[key])) {
if (_.isObject(value) && _.isObject(base[key])) {
if (!path) {
path += `${key}`;
} else {
path += `.${key}`;
}
result[key] = changes(value, base[key], path);
} else {
if (!path) {
path = key;
}
result[key] = { value, path };
}
}
});
};
return changes(object, base);
};
I'm trying to make sure that it returns not just the properties that are different, but also the direct path of that property.
For instance, if I have,
const objA = {
filter: {
tag: 1
},
name: 'a'
}
const objB = { name: 'b' };
Then getting the diff should yield:
{
filter: {
value: { tag: 1 },
path: 'filter.tag'
},
name: {
value: 'a',
path: 'name'
}
}
But right now it returns path: 'filter' always. What am I doing wrong?
Below link for quick access to lodash for the console:
fetch('https://cdn.jsdelivr.net/npm/lodash#4.17.4/lodash.min.js')
.then(response => response.text())
.then(text => eval(text))
Your current path is scoped outside of _.transform thus it will apply to all branches.
Scope it within the result of _.transform and everything is ok.
E.g.:
const getDiff = (object, base) => {
//changed
const changes = (object, base, _path = "") => {
return _.transform(object, function(result, value, key) {
// changed
let path = _path;
if (!_.isEqual(value, base[key])) {
if (_.isObject(value) && _.isObject(base[key])) {
if (!path) {
path += `${key}`;
} else {
path += `.${key}`;
}
result[key] = changes(value, base[key], path);
} else {
if (!path) {
path = key;
} else { // changed
path += `.${key}`;
}
result[key] = { value, path };
}
}
});
};
return changes(object, base);
};
I would really appreciate another pair of eyes to review why this issue persists.
Basically, a component does some check with validation functions imported from another file
...
const {emailField, phoneFieldUS, postalCodeField} = validators;
class ReturnForm extends React.Component {
...
formHasAnyErrors = () => {
console.log("phoneFieldUS type ", typeof phoneFieldUS)
console.log("postalCodeField type ", typeof postalCodeField)
const zipCodeValid = postalCodeField(form.contactInfo.postalCode);
const emailValid = emailField(form.contactInfo.email);
const mobileValid = phoneFieldUS(form.contactInfo.mobile);
if (!zipCodeValid || !emailValid || !mobileValid) {
return true;
}
return Object.values(errors.contactInfo).find(el => !!el);
};
...
}
And the validators imported looks like this:
exports.default = exports.validators = exports.validatorFactory = exports.statuses = exports.layouts = void 0;
const validatorFactory = (test, pass = () => {}, fail = () => {}) => {
return value => {
const validValue = test(value);
if (validValue === true) {
pass();
} else {
fail();
}
return validValue;
};
};
exports.validatorFactory = validatorFactory;
const validators = {
emailField: validatorFactory(value => {
return /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(value); // eslint-disable-line max-len
}),
postalCodeField: validatorFactory(value => {
return ((value.length === 5 && /^\d+$/.test(value)) ^ (value.length === 6 && /\d/.test(value) && /[a-zA-Z]/.test(value)))
}),
emptyField: validatorFactory(value => value.length > 0 && !/^\s*$/.test(value)),
phoneFieldUS: validatorFactory(value => /^\(?(\d{3})\)?[-\. ]?(\d{3})[-\. ]?(\d{4})$/.test(value))
};
exports.validators = validators;
What I absolutely don't understand is
console.log("phoneFieldUS type ", typeof phoneFieldUS) // prints function
console.log("postalCodeField type ", typeof postalCodeField) // prints undefined
Hence every time the ReturnForm component is complaining about Uncaught TypeError: postalCodeField is not a function
Like how?????? They're both defined almost the same way?????? Please tell me if I'm missing something, any help appreciated!
I have written a function to search in a nested object. The problem is that it returns undefined instead of the expected result, that is correctly logged in the console. Whats going on there?
const in1 = [1, 2];
const in2 = [1, 2];
const vDOM = {
1: {
ref: in1,
children: {
2: {
ref: in2,
children: {}
}
}
}
}
const findVDOMNode = function(instance, vDOM) {
const keys = Object.keys(vDOM);
const foundKey = keys.find(key => vDOM[key].ref === instance);
//console.log(foundKey, vDOM, "FK");
if (!keys.length) {
console.log('no keys');
return;
}
if (foundKey) {
console.log('found', vDOM[foundKey]);
return true; //vDOM[foundKey];
};
keys.map(key =>
findVDOMNode(instance, vDOM[key].children));
}
console.log('res: ', findVDOMNode(in2, vDOM));
Live example: https://stackblitz.com/edit/js-dapzsy
Just add return at the end.
return keys.map(key =>
findVDOMNode(instance, vDOM[key].children));
You could take the values of the object and check it against the instance. If an object is found, check the object as well. For iterating use some with short circuit, if the instance is found.
const
in1 = [1, 2],
in2 = [1, 2],
vDOM = { 1: { ref: in1, children: { 2: { ref: in2, children: {} } } } },
findVDOMNode = (instance, vDOM) => Object
.values(vDOM)
.some(v => v === instance
|| v && typeof v === 'object' && findVDOMNode(instance, v)
);
console.log('res: ', findVDOMNode(in2, vDOM));
it looks like you are missing a return statement on the map in the last line of the function
const in1 = [1, 2];
const in2 = [1, 2];
const vDOM = {
1: {
ref: in1,
children: {
2: {
ref: in2,
children: {}
}
}
}
}
const findVDOMNode = function(instance, vDOM) {
const keys = Object.keys(vDOM);
const foundKey = keys.find(key => vDOM[key].ref === instance);
//console.log(foundKey, vDOM, "FK");
if (!keys.length) {
console.log('no keys');
return;
}
if (foundKey) {
console.log('found', vDOM[foundKey]);
return true; //vDOM[foundKey];
};
///added this return statement
return keys.map(key =>
findVDOMNode(instance, vDOM[key].children));
}
console.log('res: ', findVDOMNode(in2, vDOM));