React JSX - Ternary operator with multiple or conditions - javascript

I'm trying to render out a specific colour scheme for my footer based on the url pathname. The site only has 3 url's that require the colour scheme so I want to target them specifically. I'm wondering if there is a way to do it using the or/pipes operator or should I just put it in a switch statement?
var urlString = '/work' || '/wip' || '/journal';
<FooterContainer theme={ window.location.pathname == urlString ? 'dark' : 'light' }>
This is my simplified code so far, just wanted to test that dark or light is returned on the component. It works for the /work url but the rest of them it doesn't.

The condition '/work' || '/wip' || '/journal' will always return '/work' since it is considered a true value, so there is no need to check the other OR conditions. This is why it works for '/work' and nothing else.
I would like to recommend two approaches for this:
One is to write a straight forward function that returns true/false based on the pathname provided.
function checkUrl(pathname) {
if (pathname === '/work' || pathname === '/wip' || pathname === '/journal') {
return true;
}
return false;
}
<FooterContainer theme={ checkUrl(window.location.pathname) ? 'dark' : 'light' }>
Or a second approach to make an array with the dark theme compatible pathnames and check if the current window.location.pathname is in this array.
var darkThemePathnames = ['/work', '/wip', '/journal'];
<FooterContainer theme={ darkThemePathnames.includes(window.location.pathname) ? 'dark' : 'light' }>
If you would like to shorten it even more then you can just do:
<FooterContainer theme={ ['/work', '/wip', '/journal'].includes(window.location.pathname) ? 'dark' : 'light' }>

Related

javascript when using multiple if conditions get the failure reason

Over the years there have been multiple answers to this question, evolving from some clunky code.
In 2022 is there a one liner or improved way to get the condition that failed in a multiple if scenario?
example one, myVarTwo fails
if (( myVarOne == "alpha") && ( myVarTwo == "beta") && ( myVarThree == "cappa"){
// do stuff
}else{
console.log("failed at ...)
}
example two, myVarThree fails
if (( myVarOne == "alpha") && (( myVarTwo == "beta") || ( myVarThree == "cappa")){
// do stuff
}else{
console.log("failed at ...)
}
I am assuming the conditions test stops at the first fail.
Firstly, your assumption that the condition test stops at the first fail is correct. The logical && operator is a short-circuit operator. It will return at the first instance of a falsy evaluation. Conversely, the || opearator returns at the first instance of a truthy evaluation.
With that said, my only guess would be to use ternary operators but I'm not sure if you would consider it to be a one liner. Especially if you have a lot more conditions to check for, the ternary operator would get really really long and not very readable. The ternary operators can be seen as simulating multiple if...else conditions being tested sequentially, with an action for each check.
const myVarOne = "alpha",
myVarTwo = "notBeta",
myVarThree = "cappa"
const printFailure = (string) => {
console.log(`Failed at ${string}`)
}
const printSuccess = () => {
console.log('All conditions satisfied!')
}
// Method 1
myVarOne != "alpha" ? printFailure("myVarOne") : myVarTwo != "beta" ? printFailure("myVarTwo") : myVarThree != "cappa" ? printFailure("myVarThree") : printSuccess()
// Method 2
myVarOne == "alpha" ? myVarTwo == "beta" ? myVarThree == "cappa" ? printSuccess() : printFailure("myVarThree") : printFailure("myVarTwo") : printFailure("myVarOne")

Combining text and JS in className after a ternary operator

I'm having trouble combining a text and CSS style after for className after a ternary/conditional. I've looked at so many different examples however nothing seems to be working.
<div className={key === active ? ({ 'column ' + styles.Active}) : ('column ')} key={key}>
Can anyone please show me how to best format this correctly? I need both the column and styles.Active classNames to appear if key === active.
Thank you in advance
this is the same solution, but the best approach
<div className={key === active ? `column ${styles.Active}` : 'column'}>
it's more readable, self explaining, and discreet, this is how you should write the code, not the otherway..
className expects a string and instead you gave it an object {'column ' + styles.Active} which is wrong.
also, i don't understand your logic. styles.Active would be an object which is of a style(style object). if that's the case you are doing it wrong again..
<div className="column" style={key === active ? styles.Active : {}}>
If you're ok with adding an npm package you can use classnames
import classNames from 'classnames';
...
<div className={classNames('column', { [styles.Active]: key === active })} key={key}>
=================
if you don't want to add an npm package
<div className={'column ' + (key === active ? styles.Active : '')} key={key}>
For readability it may be better to extract this into a variable. Though, the ternary could easily be inline.
String Literals
For those that prefer ES6+
// Ternary
const className = `column ${(key === active) ? styles.Active : ''}`;
// Or a little more readable
const className = 'column';
if (key === active) {
className += ` ${styles.Active}`;
}
...
<div className={className} key={key}>
Concatenation
It seems for the moment string concatenation is faster: (https://jsperf.com/es6-string-literals-vs-string-concatenation/49)
// Ternary
const className = 'column' + ((key === active) ? ' ' + styles.Active : '')}`;
// Or a little more readable
const className = 'column';
if (key === active) {
className += ' ' + styles.Active;
}
...
<div className={className} key={key}>
Try this one out. Take the column out , and have the ternary operated on just the key
<div className={'column ' + (key === active ? styles.Active : '')} key={key}>
I found an easy way to do it use an array and join it, it's bit old question but maybe it gonna help someone else.
className={ [ isMobile ? 'small' : 'large' , darkTheme ? 'dark' : 'light' , isSomething ? 'classX' : 'classY' ].join(' ') }

Typescript if and if not with boolean and string

I am editing an app using TypeScript React and Meteor. Currently I got the following state:
{user && ( ... )}
This shows some data only if the visitor is a logged in user. I although want to show the data only if the tournament is not cancelled. So I tried to add
{user && !tournament.state === 'cancelled' && ( ... )}
which does not work. I receive the following linter message:
Operator '===' cannot be applied to types 'boolean' and '"cancelled"'.
How can I solve this puzzle?
!tournament.state negates tournament.state, not the === that follows, resulting in true or false for that part, giving you true === 'cancelled' or false === 'cancelled'. Hence the issue with using===` on a boolean and a string.
Use !==:
{user && tournament.state !== 'cancelled' &&
Technically, you can use parentheses as well, but it wouldn't be idiomatic:
{user && !(tournament.state === 'cancelled') &&
TypeScript complains because you are trying to compare a boolean value: !tournament.state to a string: 'cancelled'.
The ! symbol is going to turn a truthy/falsy result into an boolean. This happens because assuming tournament.state is equal to 'cancelled':
!tournament.state = !'cancelled' = false
The triple equals operator then checks both value and type. Your code will not only be disliked by TypeScript, it is also incorrect, as every value of tournament.state is going to fail the check, because it will always end up as a boolean against a string. What you need is:
{user && tournament.state !== 'cancelled' && ( ... )}

Reading multiple ternary operator conditions

I've come across the following code:
if (proto.hasOwnProperty(name)) {
!(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) : invariant(false) : undefined;
}
How do you read the ternary operator in line 2?
As one of the comments says, you should probably convert this to a traditional if-else tree for readability/sanity. However, it would read like this (I haven't written it out verbatim for brevity's sake, but you get the gist):
if (!conditionOne) {
if (conditionTwo) {
return invariant(false, 'ReactClass...', name);
}
else {
return invariant(false);
}
}
else {
return undefined;
}
I figured answering this by converting to the code to an if-else tree may help you understand it a little easier :)
Try to format an indent your code for better understanding.
if (proto.hasOwnProperty(name)) {
!(
specPolicy === SpecPolicy.DEFINE_MANY //1
||
specPolicy === SpecPolicy.DEFINE_MANY_MERGED //1
) ?
process.env.NODE_ENV !== 'production' ? //2
invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) :
invariant(false)//3
: undefined;//4
}
(1) If specPolicy is neither SpecPolicy.DEFINE_MANY nor SpecPolicy.DEFINE_MANY_MERGED, then check if process.env.NODE_ENV is not "production".
(2) If so then call invariant(false, 'Re...., else call (3)invariant(false).
If (1) is true return undefined (4).
There are two ternary operators. See if this way of formating it helps:
!(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ?
process.env.NODE_ENV !== 'production' ?
invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) :
invariant(false) :
undefined;
You could use proper indents. The most inner ternary is grouped together like
condition1 ? condition2 ? value1 : value2 : value3
is the same as
condition1 ? (condition2 ? value1 : value2) : value3
With your code;
!(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ?
process.env.NODE_ENV !== 'production' ?
invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) :
invariant(false) :
undefined;

Conditionally add string to HTML with Angular expression

I have the following :
<div>{{animalType}}</div>
which evaluates to dog.
Can I conditionally add an sif animalTypeevaluates to anything other than dog?
Something like this : which doesn't work
<div>{{animalType}} {{'s' : !animalType == 'dog'}}</div>
So I would getcats
Use ternary operator in expression as follow:
<div>{{animalType}}{{animalType != 'dog' ? 's' : '' }}</div>
Alternatively
<div>{{animalType}}<span ng-show="animalType!='dog'">s</span></div>
Not tested, but try this simple snippet:
<div>{{animalType === "dog" ? animalType : "s"}}</div>
By the way, if you want to switch only between two values, from my point of view, logically appealing would be something like that:
<div>{{isDog ? "dog" : "s"}}</div>
$scope.isDog = true/false
You could also use ng-if
<div>{{animalType}}<div ng-if="animalType !== 'dog'">s</div></div>

Categories

Resources