i want to use ternary operator instead of if else conditions in react.
What i am trying to do?
I have an array of object type named 'list_info' which has type, recipient_idand recipient_email attributes.
Now i have a method named "get_text" which returns text whose value is string "to you" or the recipient email.
If the list_info type is "type_1" and props.current_user_id === list_info.recipient_id then it should
return nothing.
If the list_info type is "type_1" and props.current_user_id !== list_info.recipient_id then it should
return the list_info.recipient_email.
Now when the list_info type is anything other than "type_1" and and props.current_user_id ===
list_info.recipient_id then it should
return string "to you".
If the list_info type is anything other than "type_1" and props.current_user_id !==
list_info.recipient_id then it should return the list_info.recipient_email.
So to accomplish the above conditions i have the "get_text" method as below,
get_text = () => {
const list_info = this.props.list_info;
let text;
if (this.props.list_info.type === 'type_1') {
if (this.props.current_user_id === list_info.recipient_id) {
text = '';
} else {
text = list_info.recipient_email;
}
} else {
text = this.props.current_user_id === list_info.recipient_id
? 'you'
: list_info.recipient_email;
}
return <strong key={list_info.type}>{text}</strong>;
};
The above code works. But i think it could be made even more simple to read using ternary operator. could someone help me fix this. thanks.
Generally writing nested ternary operators will make the code unreadable. You can refactor your code as below, if you have more and more conditions/logic coming in, you can probably start using switch statement.
get_text = () => {
const { list_info, current_user_id } = this.props;
const meTextByType = list_info.type === 'type_1' ? "" : "you";
let text = current_user_id === list_info.recipient_id ?
meTextByType :
list_info.recipient_email;
return <strong key={list_info.type}>{text}</strong>;
};
get_text = () => {
const { list_info, current_user_id } = this.props;
const { type, recipient_id, recipient_email } = list_info;
const meTextByType = type === 'type_1' ? "" : "you";
let text = current_user_id === recipient_id ? meTextByType :brecipient_email;
return <strong key={type}>{text}</strong>;
};
How about local functions that describe exactly what each condition is, and by the looks of you only ever return 2 values, either 'to you' or the recipient_email prop.
getText = () => {
const isToYou = () => listInfoType !== 'type_1' && recipientId === userId
return isToYou() ? 'To You' : recipientEmail
}
Related
I'm missing something if someone can please explain it to me. I'm trying to re-write existing code into the ternary operator way.
I'm getting the following console error :
Uncaught SyntaxError: Unexpected token }
which I understand there's a condition not properly formatted which I can't seem to find. So I'm not sure what I'm missing or if I maybe misunderstand something in the filter function? Isn't the ? item.verified === true not suppose to automatically return the objects that's true?
var engagement = "social";
var audience = [{ 'verified': true, 'name': 'Steve'},
{ 'verified': false, 'name': 'Phil'},
{ 'verified': true, 'name': 'Jason'}];
let data = [];
data = audience.filter((item) => {
(engagement === "social")
? item.verified === true
: (engagement === 'social-crm')
? item.verified === false
: (engagement === 'all')
? item
})
The syntax that I understand:
data = audience.filter((item) => {
if (this.engagement === 'social-crm') {
return item.verified === true;
} else if (this.engagement === 'social') {
return item.verified === false;
} else if (this.engagement === 'all') {
return item;
}
});
Here's the fiddle I've been trying to play around with:
https://jsfiddle.net/phfilly/ya73e325/7/
Yup. Your syntax isn't right. To understand why your code isn't working, it would help if you were to re-write your if-else statements a bit.
if (this.engagement === 'social-crm') {
return item.verified === true;
} else if (this.engagement === 'social') {
return item.verified === false;
} else if (this.engagement === 'all') {
return item;
}
To this:
if(this.engagement === 'social-crm') { return item.verified === true; }
else {
if(this.engagement === 'social') {item.verified === false; }
else {
if(this.engagement === 'all') {return item;}
}
}
Now, ternary operators follow a similar nested fashion.
cond1 ? val1 : ( val2 )
Where val2 => cond2 ? val3 : (val4)
Where val4 => cond3 ? val5 : val6
So, now you can rewrite your expression like this:
this.engagement === 'social-crm' ? item.verified === true :
(this.engagement === 'social' ? item.verified === false :
(this.engagement === 'all' ? item : null))
The parenthesis matters here, because it closely mimics the nested if-elses from above.
Also note that for the inner most expression, a return value in the else must be specified. I've set it to null but you can return what you want. Do note this is the actual reason your code was failing. Apologies if the answer was long but I wanted to help you understand nested ternary operators.
A ternary operator looks like this:
something = (condition) ? a_value : a_different_value;
You forgot : a_different_value on the last case.
A nested ternary operator looks like this:
something = condition ? nested_condition ? value_if_both_conditions_are_true
: value_if_nested_condition_is_false : value_if_condition_is_false;
This works even without parentheses, but as others have mentioned, it can be hard to read. Especially when multiple conditions are checked, by use of && or || in the condition parts of this example.
Try this
You have to have a Condition for the Ternary operator as pointed by #Quentin
data = audience.filter((item) => { (engagement === "social") ?
item.verified === true : (engagement === 'social-crm') ?
item.verified === false : (engagement === 'all')?
item : null})
Deep nesting can write in a simpler way like this for ternary if-else
let userName = 'Amoos'
let isStudent = false
let age = 7
userName
? console.log(`User name: ${userName} 😊`)
: console.log('Unknow user');
isStudent ? console.log("Yes, is student 👨🎓")
: console.log('No, not a student 👨🎓');
(age<18) ? console.log("Younger 👶")
: console.log("Elder 😁")
I'm actually trying to connect my db to a react app and it keeps showing me this errors in three different places that i highlight with ">>" below
handleDBReponse(response) {
const appointments = response;
const today = moment().startOf("day"); //start of today 12 am
const initialSchedule = {};
initialSchedule[today.format("YYYY-DD-MM")] = true;
const schedule = !appointments.length
? initialSchedule
: appointments.reduce((currentSchedule, appointment) => {
const { slot_date, slot_time } = appointment;
const dateString = moment(slot_date, "YYYY-DD-MM").format(
"YYYY-DD-MM"
);
>> !currentSchedule[slot_date]
? (currentSchedule[dateString] = Array(8).fill(false))
: null;
>> Array.isArray(currentSchedule[dateString])
? (currentSchedule[dateString][slot_time] = true)
: null;
return currentSchedule;
}, initialSchedule);
for (let day in schedule) {
let slots = schedule[day];
>> slots.length
? slots.every(slot => slot === true) ? (schedule[day] = true) : null
: null;
}
this.setState({
schedule: schedule
});
}
In all three cases you're doing something like
condition ? something = somethingElse : null
So if condition is falsy, it evaluates to false null, which doesn't really make sense. I think it would be easier to read and get rid of the warnings if you did something like
if (condition) something = somethingElse
So in the first case
!currentSchedule[slot_date]
? (currentSchedule[dateString] = Array(8).fill(false))
: null;
should be
if (!currentSchedule[slot_date]) {
(currentSchedule[dateString] = Array(8).fill(false));
}
I am trying to create a reservation app. I am quite new to React, and I tried searching and I can't seem to find what the problem is.
As my code has over 400 lines I will post only the ones I'm getting an error at.
I am following this article https://medium.com/#kris101/building-appointment-scheduler-app-in-react-and-nodejs-d01f7294a9fd
Error screenshot
The specific errors are:
Line 136:11: Expected an assignment or function call and instead saw an expression no-unused-expressions
Line 139:11: Expected an assignment or function call and instead saw an expression no-unused-expressions
Line 147:7: Expected an assignment or function call and instead saw an expression no-unused-expressions
I tried disabling eslint but when I do so I'm getting more errors.
handleDBReponse(response) {
const reservations = response;
const today = moment().startOf("day"); //start of today 12 am
const initialSchedule = {};
initialSchedule[today.format("YYYY-DD-MM")] = true;
const schedule = !reservations.length
? initialSchedule
: reservations.reduce((currentSchedule, reservation) => {
const { slot_date, slot_time } = reservation;
const dateString = moment(slot_date, "YYYY-DD-MM").format(
"YYYY-DD-MM"
);
!currentSchedule[slot_date]
? (currentSchedule[dateString] = Array(8).fill(false))
: null;
Array.isArray(currentSchedule[dateString])
? (currentSchedule[dateString][slot_time] = true)
: null;
return currentSchedule;
}, initialSchedule);
for (let day in schedule) {
let slots = schedule[day];
slots.length
? slots.every(slot => slot === true) ? (schedule[day] = true) : null
: null;
}
this.setState({
schedule: schedule
});
}
I can see lots of linting issue in the above code.As of now I have fixed Expected an assignment or function call issue.
Please check the below code and let me know if it works
handleDBReponse(response) {
const reservations = response;
const today = moment().startOf('day'); // start of today 12 am
const initialSchedule: any = {};
initialSchedule[today.format('YYYY-DD-MM')] = true;
const schedule = !reservations.length
? initialSchedule
: reservations.reduce((currentSchedule: any, reservation: any) => {
const tempSchedule = currentSchedule;
const { slot_date, slot_time } = reservation;
const dateString = moment(slot_date, 'YYYY-DD-MM').format('YYYY-DD-MM');
tempSchedule[dateString] = !tempSchedule[slot_date] ? (tempSchedule[dateString] = Array(8).fill(false)) : null;
if (Array.isArray(tempSchedule[dateString])) {
tempSchedule[dateString][slot_time] = true;
}
return test;
}, initialSchedule);
for (const day in schedule) {
const tempSchedule = schedule;
const slots = tempSchedule[day];
const checkEverySlot = slots.every((slot: boolean) => slot === true);
if (slots.length && checkEverySlot) {
tempSchedule[day] = true;
}
}
this.setState({
schedule,
});
}
Note: It is good practice to write identifier in camel case.
This issue is around your use of ternary statements;
!currentSchedule[slot_date] ? (currentSchedule[dateString] = Array(8).fill(false)) : null;
Array.isArray(currentSchedule[dateString]) ? (currentSchedule[dateString[slot_time] = true) : null
slots.length ? slots.every(slot => slot === true) ? (schedule[day] = true) : null : null;
You can't use ternary statements in this way, you should replace these with individual if statements
e.g
if(currentSchedule[slot_date]) currentSchedule[dateString] = Array(8).fill(false)
An example of a proper use of ternaries would be when assigning a variable:
let myVar = x === 10 ? 'x is 10' : 'x is not 10'
The function handleDBReponse doesn't seems to be a well defined function. Try adding public before its name. Like public handleDBReponse(response) {...}.
I want to create a function that can be general as possible but It doesn't work now.
I have two case :
Check if the state of a state is not empty or true and if my item is equal to him, I want to reset him by calling resetState() and set to false and empty string
Check if the state of a state is not empty and if my item is equal to him, I want to reset him by calling resetState()and the empty string
My problem is : I try to replace stateItem.checkedA by something like stateItem.item to avoid repetitions but doesn't work for me, is it possible in react to do that ?
This is what I have :
const [stateBoolean, setStateBoolean] = React.useState({
checkedA: false,
checkedB: false
});
const [stateItem, setStateItem] = React.useState({
checkedA: "",
checkedB: "toto",
checkedC: "onlyHere not in Boolean"
});
const check = (listState) => {
listState.map(item => {
(stateBoolean.checkedA === true || stateItem.checkedA !== "") &&
item === "checkedA"
? (resetChange("checkedA", "stateItem"),
resetChange("checkedA", "stateBoolean"))
: null;
(stateBoolean.checkedB === true || stateItem.checkedB !== "") &&
item === "checkedB"
? (resetChange("checkedB", "stateItem"), resetChange("checkedB", "stateBoolean"))
: null;
stateItem.checkedC !== "" && item === "checkedC"
? resetChange("checkedC", "stateItem")
: null;
});
};
What I expected, but not working:
const checkWanted = (listState) => {
listState.map(item => {
(stateBoolean.item === true || stateItem.item !== "") &&
(item === "checkedB" || item === "checkedA")
? (resetChange(item, "stateItem"), resetChange(item, "stateBoolean"))
: null;
stateItem.checkedEOther !== "" && item === "checkedEOther"
? resetChange(item, "stateItem")
: null;
});
};
Any idea?
Use stateBoolean[item] instead, you can access properties of an object like an array
The function map return a new Array mdn description
If you want to iterate on a array and do something you should use forEach or a for loop.
In order to filter an array on possibly 2 parameters I have written the following code:
filterStudies(searchString?: string) {
if (searchString && !this.selectedModalityType) {
this.studies = this.fullStudyList.filter(function (study) {
return (study.Code.toUpperCase().includes(searchString.toUpperCase())) ||
(study.Description.toUpperCase().includes(searchString.toUpperCase()));
})
} else if (!searchString && this.selectedModalityType) {
console.log(this.selectedModalityType)
this.studies = this.fullStudyList.filter(function (study) {
return (study.ModalityType.Code.toUpperCase() === this.selectedModalityType.toUpperCase())
})
} else if (searchString && this.selectedModalityType) {
this.studies = this.fullStudyList.filter(function (study) {
return (study.Code.toUpperCase().includes(searchString.toUpperCase())) ||
(study.Description.toUpperCase().includes(searchString.toUpperCase())) &&
(study.ModalityType.Code.toUpperCase() === this.selectedModalityType.toUpperCase())
})
}
}
filterStudies(searchString?: string) is called when typing in a textbox that.
The other way of filtering could be by selecting a value from a dropdown box. Achieved by this code:
handleSelection(value:any){
this.selectedModalityType = value;
console.log(value)
this.filterStudies()
}
All works fine until this code is hit:
this.studies = this.fullStudyList.filter(function (study) {
return (study.ModalityType.Code.toUpperCase() === this.selectedModalityType.toUpperCase())
})
Error message : ERROR TypeError: Cannot read property 'selectedModalityType' of undefined, I see it is actually logged in the line before.
What am I missing??
Thanks,
In your funtcion, this is not the same this as the line before.
This will work:
let self = this;
this.studies = this.fullStudyList.filter(function (study) {
return (study.ModalityType.Code.toUpperCase() === self.selectedModalityType.toUpperCase())
})
You can read this to learn more: https://github.com/Microsoft/TypeScript/wiki/%27this%27-in-TypeScript
The this keyword in JavaScript (and thus TypeScript) behaves differently than it does in many other languages. This can be very surprising, especially for users of other languages that have certain intuitions about how this should work.
(...)
Typical symptoms of a lost this context include:
A class field (this.foo) is undefined when some other value was expected