How to render conditional jsx using ternary operator in react? - javascript

i want to use ternary operator for conditional rendering of jsx using react and javascript.
below is my code,
const Parent = () => {
return (
<Child
isChecked={true}
isMany={true}
/>
);
};
const Child = (props) => {
const name=defaultTo(props.optionName, 'name');
return (
{props.isMany
? `${props.getValue().length} ${name}${
props.getValue().length > 1 ? 's' : ''
} selected`
: props.getValue()[0].label
}
);
}
the above code works and it returns output like "2 names selected" or "1 name selected" based on getValue length. here Child component is reusable and isChecked prop is optional. it may or maynot be passed as prop to this Child component.
Now if the isChecked prop is true, i want to display output like "2 selected" or "1 selected" which depends on getValue length.
how can i modify the above code to do so.
could someone help me with this. thanks.
EDIT:
below is what i have tried.
const Child = (props) => {
const name= props.isChecked ?
defaultTo(props.optionName, '')
: defaultTo(props.optionName, 'name');
return (
{props.isMany
? `${props.getValue().length} ${name}${
(props.getValue().length > 1 && !isChecked) ? 's' : ''
} selected`
: props.getValue()[0].label
}
);
}
this kind of works but still displays that 's' if more than one count so the output is like below
1 selected
2 s selected
3 s selected
....

I'd do much of the work before the return, something along these lines:
const Child = (props) => {
const {isChecked, isMany, optionName} = props;
const value = props.getValue();
const {length} = value;
const nameDisplay = isMany && `${defaultTo(optionName, "name")}${length === 1 ? "" : "s"}`;
return (
isMany
? isChecked
? `${length} selected`
: `${length} ${nameDisplay}`
: value[0].label;
);
};
I should note that just adding an s works for name, but doesn't work for many other nouns in English (bus for instance, or mouse). Making plurals in English is, sadly, fairly complicated in practice. Rather than accepting just optionName, you might consider accepting something that includes both the singular and the plural.
Side note: ? : is a ternary operator (an operator accepting three operands, like a binary operator accepts two operands and a unary operator accepts one), and it's JavaScript's only ternary operator at the moment, but that could change. Its proper name is the conditional operator.

You can make another ternary operator.
const Child = (props) => {
const name=defaultTo(props.optionName, 'name');
return (
{props.isChecked ?
props.getValue().length + " selected" :
(props.isMany
? `${props.getValue().length} ${name}${
props.getValue().length > 1 ? 's' : ''
} selected`
: props.getValue()[0].label)
}
);
}

Related

What does && mean when used this way, and what is it called? [duplicate]

This question already has answers here:
What is "x && foo()"?
(5 answers)
Closed last year.
I know that it's called logical and but i mean specifically this way of using it,
I was looking at some jsx packages and found this example
const Button = props => (
<button className={'large' in props && 'large'}>
{props.children}
<style jsx>{`button{
.large {padding: 50px;}
`}</style>
</button>
)
What does 'large' in props && 'large' mean? I know large is just a class so its irrelevant but can someone put into words what the operator is actually doing?
Is it a short form of some kind of if statement and if so how would you type it out if it wasnt shortened? i hope this makes sense!!
edit: here's another example
<p>{params.categoryName === "rent" ? "rent" : "sale"}</p>
{loading ? (
<h1>Loading</h1>
) : listings && listings.length > 0 ? (
<>
<ul>
{listings.map((listing) => (
<ListingItem listing={listing.data} id={listing.id} />
))}
</ul>
</>
) : (
<p>No listings for {params.categoryName}</p>
)}
Is it clearer written as a ternary ?
props.includes("large") ? 'large' : '';
or a good old if/else ?
if(props.includes("large")){
return "large";
} else {
return "";
}
'large' in props is the same as props.includes("large"), it returns a boolean. If the boolean is true, then the next condition is evaluated with "and" (&&) . Since a string is truthy (if it has a length), it is returned as the result of the operation, that is, "large".
It is simply a quick way to say "if x is truthy, return y".
As MDN puts it: "if all values are truthy, the value of the last operand is returned." (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND#description).
If it wasn't shortened it could look something like this:
x && y;
if(x) {
return y;
} else {
return false;
}
&& is the logical AND operator in javascript. The logical AND operator && returns true if both operands are true, and returns false otherwise.
Example1:
className={'large' in props && 'large'}
In the first example, 'large' in props && 'large' is used as an Inline If with Logical && Operator which is equivalent to
if('large' in props && 'large'){
return true;
}
else{
return false;
}
Example2:
Similarly, in the second example
listings && listings.length > 0
which is equivalent to
if(listings && listings.length > 0) {
// display list
}
else {
// no list error message here
}
Hope, this will answer you question.

Break map loop inside return in component

I'm trying to loop into an array to create the component content, if condition on array element is not satisfied then break the loop and return 1 component
leaves.map(leave => leave.id === currentUser.id ? <div> {leave} </div> : <div> no leaves </div>)
This is the code I have so far, no leaves is printed out every time leave.id is different than currentUser's id
What I need to is, print no leaves only when none of the leaves's id matches the currentUser's id and therefore I want to break the map after printing no leaves
You should use Array.prototype.some. In your case, you would pass a function to the method to check whether it satisfies your condition and use the ternary operator to render the content.
const arrWithId = [670760658, 250026214, 126834449, 987103760, 882536150, 666896331, 488576796, 186598055, 103751309, 419995457, 503676712, 487691896, 744253979, 269253696, 102370148, 237328910, 409016979, 979651614, 743486466, 445993562, 779323321, 939834768, 296731253, 925812473, 114149678];
const arrWithoutId = [123456789, 250026214, 126834449, 987103760, 882536150, 666896331, 488576796, 186598055, 103751309, 419995457, 503676712, 487691896, 744253979, 269253696, 102370148, 237328910, 409016979, 979651614, 743486466, 445993562, 779323321, 939834768, 296731253, 925812473, 114149678];
const id = 123456789;
const checker = elem => id === elem;
console.log(`With ID: ${arrWithId.some(checker) ? "yes" : "no"}`)
console.log(`Array: ${arrWithId}`);
console.log(`Without ID: ${arrWithoutId.some(checker) ? "yes" : "no"}`)
console.log(`Array: ${arrWithoutId}`);

How to do a nested ternary in reactjs

I have two variables, search and selectedAsset. When Search or selectedAsset is shown I would like to set a new variable named optionalparamaters which excutes when search is true or selectedAsset is true. I am trying to pass the optioinalParamaters variable into the url param depending on its case.
let optionalSearch = search === '' ? '' : `?asset_type=${search}`
let optionalSelectedAsset = selectedAsset === '' ? '' : `?asset_type=${selectedAsset}`
let results = await verifiedGet(`get_all_reviews/${(currentPage - 1) * resPerPage}/${resPerPage}${optionalSearch}`, user.user)
Right now obviously you can see that the optionalSearch is only being called, hence why I wanted to create that new variable optionalParamaters which I can pass through based on whether the condition is sett to search or selectedAsset.
Updated code:
let optionalParams = search === '' ? '' : `?asset_type=${search}` : (selectedAsset === '' ? '' : `?asset_type=${selectedAsset}` )
This is a solution very readable without ternary.
const params = new URLSearchParams();
params.set('resPerPage', resPerPage);
if ( !!search ) {
params.set('asset_type', search);
params.set('optionalSearch', true);
}
if ( !!selectedAsset ) {
params.set('asset_type', selectedAsset);
params.set('optionalSearch', true);
}
const url = `/${(currentPage - 1) * resPerPage}/?${params.toString()`;
let results = await verifiedGet(url, user.user);

Conditionals in React

How do I use conditionals in React?
Essentially, for customerClassesRemaining, I currently say "class(es)" but I want to write code that says if there's one class, use "class," and if there's more than one class, use "classes." Thanks!
render() {
const loadBoxes = (
Array.from({ length: 20 }).map((n, i) => (
<LoadBox key={`${i}${n - 1}key`} />
))
);
const customerBoxes = !this.props.customersLessThanFive ? loadBoxes
: this.props.customersLessThanFive.map((customer, i) => (
if (customer.classes_remaining == 1) {
customerClassesRemaining2 = {`${customer.classes_remaining} class left`}
}
else {
customerClassesRemaining2 = {`${customer.classes_remaining} classes left`}
}
<CustomerFewerFiveBox
key={customer.id}
customerIndex={i + 1}
customerName={`${customer.firstName} ${customer.lastName}`}
customerClassesRemaining={`${customer.classes_remaining} class(es) left`}
customerPackage = {customer.name}
customerExpiration = {`Expiration: ${customer.expiration_date}`}
/>
))
you can try,
customerClassesRemaining2 = customer.classes_remaining == 1 ? `${customer.classes_remaining} class left` : `${customer.classes_remaining} classes left`;
Using ternary operators like:
customerClassesRemaining={`${customer.classes_remaining} class${customer.classes_remaining > 1 ? 'es' : ''} left`}

Using Filter Function to Return React Component - Code Review

I dont understand what I am doing wrong here. I am using Immutable.js & React in my app. I am calling Immutable.js's filter function to refine the collection based on the if condition & return array of React components.
Its actually return 'svgTemplateState' instead of the React component collection.
let getUpdatedTem = ( renderType, svgTemplateState ) => {
switch( renderType ){
case( "Template Selection" ):
return( svgTemplateState.filter(( templateType ) => {
if( templateType.get( "templateNo" ) > -1 ){
let temType = templateType.get( "type" );
return(
<TemplatePath
temData = { templateType }
key = { temType } />
);
}
}));
case( "Preview" ):
...
Immutable filters should return a boolean, indicating whether or not you want the template to be a part of the collection that you are returning. In your case, you're returning a React component.
You're iterating svgTemplateState, which appears to be a Map (it's not entirely clear to me what it is). What you should be iterating is a collection of templates, and check the template number on each template within the collection. You'd have something (simplified) like:
let newCollection = templatesCollection.filter( template => template.get( "id" ) > -1);
Is what you want to find the first Item that match the condition? like .findEntry() ?
return( svgTemplateState.filter(( templateType ) => {
if( templateType.get( "templateNo" ) > -1 ){
let temType = templateType.get( "type" );
return(
<TemplatePath
temData = { templateType }
key = { temType } />
);
}
}));
Assuming svgTemplateState is an array, replace the "filter" method in the above code with "map". If svgTemplateState is an object with pairs then use a for...in to iterate over svgTemplateState, check the condition and push the component to a temp object which you can return after the loop.

Categories

Resources