use function instead of multiple if else - javascript

this is my code and I want to break it to multiple function(clean code!), for these two section
(status===edited) and (status === added) or two different function for (dataindex===ReportEffectiveDate) and (dataindex=== EffectiveDate).how can I put these if else statement in a separate function then I use this function for each status. totally I want to know which way is better : I use multiple if and else if or use multiple function for this code? thanks for your help!
function handleTableRowChange(record: LoadModel, oldValue: any, newValue: any, dataIndex: string) {
console.log(record, oldValue, newValue, dataIndex);
const status: RowStatus = tableStore.getRowStatus(record);
if (!!newValue) {
if (dataIndex === 'ReportEffectiveDate') {
if (record.EffectiveDate > record.ReportEffectiveDate) {
record.EffectiveDate = null;
tableStore.update(record);
Modal.error({
content: translate('ReportEffectiveDatecantbelessthanoldeffectivedate'),
});
console.log('error');
} else if (record.EffectiveDate == record.ReportEffectiveDate) {
record.ReportEffectiveDate = null;
tableStore.update(record);
}
}
if (dataIndex === 'EffectiveDate') {
if (status === 'added') {
const isValid: boolean = checkIsEffectiveDateValid(record);
if (!isValid) {
record.EffectiveDate = null;
tableStore.update(record);
}
} else if (status === 'edited') {
const maxEffectiveDateRecord: LoadModel = getMaxEffectiveDateRecord(record);
if (record.EffectiveDate > maxEffectiveDateRecord.EffectiveDate) {
if (newValue < maxEffectiveDateRecord.EffectiveDate) {
record.EffectiveDate = oldValue;
tableStore.update(record);
}
}
}
}
}
}

You are still going to need to add checks to see what to call. You can break things up into a function and call it. Might be simple to use a switch
function handleTableRowChange(........) {
..........
switch (dataIndex) {
case 'ReportEffectiveDate':
reportEffectiveDateFunction(record);
break;
case 'EffectiveDate':
effectiveDateFunction(record);
break;
case 'edited':
editedFunction(record);
break;
}
}
Other option is to use an object or class with the methods
const processingFunctions = {
ReportEffectiveDate: (report) => {
console.log('ReportEffectiveDate', report);
},
EffectiveDate: (report) => {
console.log('EffectiveDate', report);
},
edited: (report) => {
console.log('edited', report);
},
}
function handleTableRowChange(........) {
..........
const action = processingFunctions[dataIndex];
if (action) {
action(report);
} else {
// no command found....
}
}

It looks like your using TypeScript... Like any OOP-like language, you can actually take it one level higher and define an interface.
For readability sake, I would recommend using functions inside of the if-else-if-if... or switch over to case statements. Moving the code into functions helps with maintainability as you change the function itself, and you won't be changing the if-else part of the code, less code changes, less mistakes.

Related

JS is or is not if else

How could I simplify this action below.
I realize this is ridiculous.
But everything I'm trying to do, either one works and one doesn't and vice versa.
I need to send data if this field is not empty. if it is empty, then don't send it: admin|power
it's either null or not
const mreq = await Model.findOne({
where: {
id: req.params.id,
old: req.params.times
}
})
if (!mreq) {
return
} else if (mreq.admin == null) {
return
} else if (mreq.admin) {
res.json(mreq.admin)
} else if (mreq.power == null) {
return
} else if (mreq.power) {
res.json(mreq.power)
}
You don't need all the branches that don't return anything - just test for the two values to be .jsond in two ifs. Use optional chaining to keep things concise.
const mreq = await Model.findOne({ where: { id: req.params.id, old: req.params.times } })
if (mreq?.admin) {
res.json(mreq.admin)
} else if (mreq?.power) {
res.json(mreq.power)
}
Considering that perhaps the property "admin" can be boolean (I don't konw)
You can do something like this:
if(mreq && mreq.admin !== null) {
res.json(mreq.admin);
return;
}
if (mreq.power) { res.json(mreq.power) }
I hope you find it useful.

Why can't I refactor those accumulating ifs by using a jump table?

I try to do a minor refactoring, but it breaks all tests.
I have a lot of ifs that I'd like to get rid off by using a jump table.
I want to go from here :
export class Pharmacy {
constructor(drugs = []) {
this.drugs = drugs
}
updatePharmacyBenefits() {
this.drugs.forEach((drug) => {
if (drug.name !== 'Magic Pill')
drug.setBenefitStrategy(new MagicPillStrategy())
if (drug.name === 'Herbal Tea')
drug.setBenefitStrategy(new HerbalTeaStrategy())
if (drug.name === 'Fervex')
drug.setBenefitStrategy(new FervexStrategy())
if (drug.name === 'Dafalgan')
drug.setBenefitStrategy(new DafalganStrategy())
drug.updateBenefit()
drug.updateExpiration()
})
return this.drugs
}
}
to here :
export class Pharmacy {
constructor(drugs = []) {
this.drugs = drugs
}
updatePharmacyBenefits() {
const drugStrategies = {
'Herbal Tea': new HerbalTeaStrategy(),
'Magic Pill': new MagicPillStrategy(),
Fervex: new FervexStrategy(),
Dafalgan: new DafalganStrategy(),
}
const specialsDrugs = ['Herbal Tea', 'Fervex', 'Magic Pill', 'Dafalgan']
this.drugs.forEach((drug) => {
if (drug.name.includes(specialsDrugs))
drug.setBenefitStrategy(drugStrategies[drug.name])
drug.updateBenefit()
drug.updateExpiration()
})
return this.drugs
}
}
I have no meaningful errors messages, I can just observe all my tests failing has if nothing has happened.

Why is one state variable updating and the other not?

I am brand new to React and I thought I was doing this correctly. I am trying to keep score for a trivia game I'm developing. When I set state, the score is updating but the number of correct responses is not. Interestingly, this is only the case when I deploy the site to firebase, it works as expected when served locally.
This function is in the parent game component. this.state.points is incrementing, this.state.numberCorrect/Incorrect is not.
childSubmitAnswer(dataFromChild) {
if (dataFromChild.correct === true) {
this.setState((prevState) => {
return {
numberCorrect: prevState.numberCorrect++,
points: prevState.points + dataFromChild.points
}
});
} else {
this.setState((prevState) => {
return {
numberIncorrect: prevState.numberIncorrect++,
points: prevState.points - dataFromChild.points
}
});
}
console.log(this.state.numberCorrect);
}
This is the function called in the child component which is displaying the question.
handleSubmit(event) {
event.preventDefault();
let verification = new AnswerVerification();
this.answerSubmitted();
if (verification.verifyAnswer(this.state.submissionValue, this.state.answer)) {
let data = {
correct: true,
points: this.props.points
}
this.props.childSubmitAnswer(data);
} else {
let data = {
correct: false,
points: this.props.points
}
this.props.childSubmitAnswer(data);
}
}
Ciao, I think the problem is on childSubmitAnswer function. Try to modify it like that:
childSubmitAnswer(dataFromChild) {
if (dataFromChild.correct === true) {
this.setState((prevState) => {
return {
numberCorrect: prevState.numberCorrect + 1,
points: prevState.points + dataFromChild.points
}
});
} else {
this.setState((prevState) => {
return {
numberIncorrect: prevState.numberIncorrect + 1,
points: prevState.points - dataFromChild.points
}
});
}
console.log(this.state.numberCorrect);
}
Explanation: in Javascript when you use ++ after the operand, the value will be returned before the operand is increased. Example:
let a = 0;
console.log(a++); // shows 0
console.log(a); // shows 1

How to make this setState function non recursive

I am learning react and is in very early stages. I was trying to add a object to an array from another component to a different component. I was able to achieve this using props but now when I try to set it in this.state setState calls the render function again thus triggering this function again. I was able to solve this problem using a button but I don't want to do it this way. Is there some better way to do this?
getData() {
if (this.props.data.employeeData !== undefined) {
if (this.props.isNewEmployee === "true") {
this.setState({
isNewEmployee: "true",
});
setTimeout(() => {
if (this.state.isNewEmployee === "true") {
console.log(this.props.data.employeeData.firstName);
var joined = this.state.EmployeesList.concat(this.props.data.employeeData);
this.setState({
EmployeesList: joined,
isNewEmployee: "false",
})
}
else {
console.log("Don't know what's happening anymore");
}
}, 100);
}
else {
console.log("No new employee added");
}
}
else {
console.log("Something went wrong");
}
}
render() {
return (
<div>
{this.getData()}
{this.renderTable()}
{this.renderFloatingActionButton()}
</div>
)
}
If the intent of the props is to add the new data to the table I would be doing something in these lines.
componentWillReceiveProps(nextProps) {
if (this.props.data.employeeData && nextProps.isNewEmployee !== this.props.isNewEmployee) {
console.log(this.props.data.employeeData.firstName);
var joined = this.state.EmployeesList.concat(this.props.data.employeeData);
this.setState({
EmployeesList: joined,
isNewEmployee: "false",
});
} else {
console.log("No new employee added");
}
}
render() {
return (
<div>
{this.renderTable()}
{this.renderFloatingActionButton()}
</div>
)
}

If else in foreach

I have an array arr=[{key: 'first'},{key: 'second'} ...], I want to go through that array and check if an element with a specific key exist and do something.
arr.forEach(element => {
if(element.key === 'first') {
// do something
} else {
// do something else
}
if(element.key === 'second') {
// do something
} else {
// do something else
}
});
The thing is that when it goes through array, it first sees 'first' and it goes through if() statement, but it also goes through else() statement of 'second' item because it did't find it, and so it does when foreach goes through other items in array. I don't know how to make it to go through array one time and set if() else() appropriately. So when it finds 'first' I want it just to do if() of that item and not else() of others. I hope you understand. Thanks in advance!
Edit: My logic behind this code is that when I call database and find that array if there is no 'firstExercise' in that array, then it should add it to that db (I am using firebase so in else() I am calling db to create that exercise), and if there is'firstExercise' in array do nothing. Sorry for not clarifying that.
Edit2: Here is my original code:
res.forEach(element => {
if (this.numbOfFinished === 1) {
if (element.key === 'firstExercise') {
console.log('has')
} else {
awardName = 'firstExercise'
this.homeService.addAward(this.userId, awardName).then(() => {
this.awardName = 'firstExercise';
this.awarded = true;
});
}
}
});
if (this.numbOfFinished === 5) {
if (element.key === 'fifthExercise') {
console.log('has')
} else {
awardName = 'fifthExercise'
this.homeService.addAward(this.userId, awardName).then(() => {
this.awardName = 'fifthExercise';
this.awarded = true;
});
}
}
});
I personally like to create arrays which makes the relation between a key and functions. So I can iterate and call the proper one.
What I like in this solution instead of using a switch/case or if/else forest is that you can apply automatic treatments and that you can easily make it to evolve.
const mapKeyFunc = [{
key: 'first',
func: async(x) => {
console.log('Do something for key first');
// here you can perform an async request and modify `this`
},
}, {
key: 'second',
func: async(x) => {
console.log('Do something for key second');
// here you can perform an async request and modify `this`
},
}];
const doStuff = async(arr) => {
for (let i = 0; i < arr.length; i += 1) {
const mapElement = mapKeyFunc.find(x => x.key === arr[i].key);
await mapElement.func.call(this, arr[i]);
}
};
const arr = [{
key: 'first',
otherStuff: 0,
}, {
key: 'second',
otherStuff: 42,
}];
doStuff(arr).then(() => {}).catch(e => console.log(e));
If you don't need the treatment to be synchronous, here we have an asynchronous method
const mapKeyFunc = [{
key: 'first',
func: async(x) => {
console.log('Do something for key first');
// here you can perform an async request and modify `this`
},
}, {
key: 'second',
func: async(x) => {
console.log('Do something for key second');
// here you can perform an async request and modify `this`
},
}];
const doStuff = async(arr) => {
await Promise.all(arr.map(x => mapKeyFunc.find(y => y.key === x.key).func.call(this, x)));
};
const arr = [{
key: 'first',
otherStuff: 0,
}, {
key: 'second',
otherStuff: 42,
}];
doStuff(arr).then(() => {}).catch(e => console.log(e));
If you only want one option out of them to be executed (and then exiting out of the function), you could use else if statements like so:
arr.forEach(element => {
if(element.key === 'first') {
// do something
} else if(element.key === 'second') {
// do something
} else {
// do something else
}
});
This will do pretty much exactly what you expect. If element.key == 'first', it'll do block one. Else, if element.key == 'second', it'll do block two. Else, it'll do block three.
You need to merge the if statements like this:
arr.forEach(element => {
if(element.key === 'first') {
// do something
} else if(element.key === 'second') {
// do something else
}
});
element.key has a single value in each iteration and you therefore need a single level of conditioning.

Categories

Resources