How to user null in map React JS - javascript

I am making an application in React JS. It consists of list of the user for which book is available, taken or requested, but when the book is filtered from the store based on user the line of the invalid user still arrives.
return (
<div>
<h1>List of Books</h1>
{filterValues.map((books) => (
<Segment.Group key={books.id}>
{(books.name === user!.username || books.name === null) &&
(books.requestedBy === user!.username ||
books.requestedBy === null) ? (
<Segment>
<Item.Group>
<Item>
{console.log(books)}
<Item.Image size="tiny" circular src="/assets/books.jpg" />
<Item.Content>
<Item.Header as="a">{books.bookName}</Item.Header>
<Item.Description>
{books.isRequested ? (
<Button
name={books.bookName}
loading={target === books.bookName && submitting}
onClick={(e) => onRequestClick(e, "cancel", books.id)}
color="red"
type="button"
content="Cancel Request"
/>
) : books.isTaken ? (
<div>
<Label basic color="red">
This book is taken By you
</Label>
<Button
name={`return${books.bookName}`}
loading={
target === "return" + books.bookName && submitting
}
color="brown"
onClick={(e) => returnBook(e, books.id)}
type="button"
content="Return this Book"
/>
</div>
) : (
<Button
name={books.bookName}
loading={target === books.bookName && submitting}
onClick={(e) =>
onRequestClick(e, "request", books.id)
}
color="green"
type="button"
content="Request For Book"
/>
)}
</Item.Description>
</Item.Content>
</Item>
</Item.Group>
</Segment>
) : null}
</Segment.Group>
))}
<Segment clearing></Segment>
</div>
);
For example for the list of books i filtered 5 books in map and UI is something like :
How Can i remove those line

Your filtering logic is placed within the .map prototype method itself, so when you are returning null, it's still placed within an empty <Segment.Group> element. Therefore I guess that this element provides the styles which result in rendering those lines.
If you want to truly filter the results and omit any returns for the ones that do not match, it would be best to first call .filter() on your array and omit the null values returned by map:
{
filterValues
.filter(books =>
(books.name === user!.username || books.name === null)
&& (books.requestedBy === user!.username || books.requestedBy === null)
).map(books =>
<Segment.Group key={books.id}>
// Segment items here without the conditional rendering of elements
</Segment.Group>
)
}

I think this is because you are checking under <Segment.Group:
{filterValues.map(books => (
<Segment.Group key={books.id}>
{((books.name === user!.username || books.name === null) && (books.requestedBy === user!.username || books.requestedBy === null))
? /* CREATE THE ITEM */
: null
}
</Segment.Group>
))}
Thus, when it is evaluated to null, it still creates a <Segment.Group> which is shown as empty item in UI.

Related

Show corresponding blocks and including extras depending on selection - React

I have this code below - it is designed to show three different packages depending on price point, so for example 'The Works' will show all three of the last three columns and the orange styled project value and 'The Starter' will show the corresponding price point but add a low opacity class to the second and third column when selected. Currently I have this working when the info is pulled in from contentful but I have a requirement to make this clickable. My confusion is where the elements aren't mapped via an array so I can't add an iterator to target it that way. I don't really want to write three functions as that is just messy and but if that is the only way then
<FlexInline>
<HalfWidth>
<CostTitle onClick={() => toggleVisibilty()} className={props.works == true && props.scaler == true && props.starter == true ? "active-cost-title-orange" : "inactive-cost-title"}><h3>The Works</h3></CostTitle>
<CostTitle onClick={() => toggleVisibilty()} className={props.scaler == true && props.starter == true && props.works != true ? "active-cost-title-blue" : "inactive-cost-title"}><h3>The Scaler</h3></CostTitle>
<CostTitle onClick={() => toggleVisibilty()} className={props.starter == true && props.scaler != true && props.works != true ? "active-cost-title-black" : "inactive-cost-title"}><h3>The Starter</h3></CostTitle>
</HalfWidth>
<HalfWidth>
{props.works == true && props.scaler == true && props.starter == true ? (
<>
<CostAmount className="active-cost-title-orange">£{props.projectValue}</CostAmount>
<PlusVat className="active-cost-title-orange">+VAT</PlusVat>
</>
) : null}
{props.scaler == true && props.starter == true && props.works != true ? (
<>
<CostAmount className="active-cost-title-blue">£{props.projectValue}</CostAmount>
<PlusVat className="active-cost-title-blue">+VAT</PlusVat>
</>
) : null}
{props.starter == true && props.scaler != true && props.works != true ? (
<>
<CostAmount className="active-cost-title-black">£{props.projectValue}</CostAmount>
<PlusVat className="active-cost-title-black">+VAT</PlusVat>
</>
) : null}
</HalfWidth>
</FlexInline>
<FlexInline>
<ThirdWidth>
{props.starterContent.map((block) => (
<CostingBlock className={props.starter == true ? "active-cost-block" : "inactive-cost-block"}>
<CostingSubheading>{block.costingTitle}</CostingSubheading>
<CostingContent>{documentToReactComponents(block.costingCopy.json)}</CostingContent>
</CostingBlock>
))}
</ThirdWidth>
<ThirdWidth>
{props.scalerContent.map((block) => (
<CostingBlock className={props.scaler == true ? "active-cost-block" : "inactive-cost-block"}>
<CostingSubheading>{block.costingTitle}</CostingSubheading>
<CostingContent>{documentToReactComponents(block.costingCopy.json)}</CostingContent>
</CostingBlock>
))}
</ThirdWidth>
<ThirdWidth>
{props.theWorksContent.map((block) => (
<CostingBlock className={props.works == true ? "active-cost-block" : "inactive-cost-block"}>
<CostingSubheading>{block.costingTitle}</CostingSubheading>
<CostingContent>{documentToReactComponents(block.costingCopy.json)}</CostingContent>
</CostingBlock>
))}
</ThirdWidth>
</FlexInline>

Displaying Dynamic arrays with map, which are not changing when changing the value in SELECT

I am displaying some data with Map, basically there are multiple arrays that are coming in as props using useAppContext()
In the navbar component there is a Select button, when changing the arrays with that Select, I want to show the data of that Array below in the component.
The data is displayed with MAP.
I have checked that the value of Select "currentCategory" is changing but the new data is not displayed with MAP Function.
When the page is reloaded, new data which is for the new "currentCategory" is displayed.
MAP Component
{currentCategory &&
creations.filter(
creation =>
creation.cat_id === currentCategory.id &&
creation.set_global === 'Yes' &&
creation.frame.height === currentTemplate.frame.height &&
creation.frame.width === currentTemplate.frame.width
).length > 0 ? (
<div className={styledm.list}>
{currentCategory &&
creations
.filter(
creation =>
creation.cat_id === currentCategory.id &&
creation.set_global === 'Yes' &&
creation.frame.height === currentTemplate.frame.height &&
creation.frame.width === currentTemplate.frame.width
)
.map(creation => (
<React.Fragment key={`creations_${creation.id}`}>
{console.log('currentCategory', currentCategory)}
<div
style={{
alignItems: 'center',
cursor: 'pointer',
border: '1px solid rgba(0,0,0,0.2)',
padding: '5px',
}}
onClick={() => handleLoadTemplate(creation)}
>
<img width="100%" height="100%" src={`${creation.preview}?tr=w-320`} alt="preview" />
</div>
</React.Fragment>
))}
</div>
) : (
<NoRecord>No Templates for this category</NoRecord>
)}
Please let me know what else should I share.

Array.prototype.map() expects a value to be returned at the end of arrow function

I have this array.map() arrow function and have the following error:
"Array.prototype.map() expects a value to be returned at the end of arrow function array-callback-return"
Here is my code:
{productList.map((val) => {
const category = val.CategoryName;
// const quantity = val.ProductQuantity
if (category === "MotorcycleParts") {
if (val.ProductQuantity !== 0) {
return (
<div>
<div>
<div class="buyNowBtnDiv">
{localStorage.getItem("username") === "" ||
localStorage.length === 0 ? (
<div id="buyAddBtn">
</div>
) : (
<div id="buyAddBtn">
</div>
)}
</div>
</div>
</div>
);
}
}
})}
I have read about the error and I see it has something to do with requiring a returning value, but I do have this?
A code example with a fix would help, I think it would be something simple.
You could just return null when the listed conditions are not matched:
{productList.map((val) => {
const category = val.CategoryName;
// const quantity = val.ProductQuantity
if (category === "MotorcycleParts") {
if (val.ProductQuantity !== 0) {
return (
<div>
<div>
<div class="buyNowBtnDiv">
{localStorage.getItem("username") === "" ||
localStorage.length === 0 ? (
<div id="buyAddBtn">
</div>
) : (
<div id="buyAddBtn">
</div>
)}
</div>
</div>
</div>
);
}
return null;
}
})}
map has to return a value for each item.
If you want to do some filtering, you should consider using Array.prototype.filter() before, so you can remove the ifs in your map.
The code is also way more easy to read.
{productList.filter(val => val.CategoryName === "MotorcycleParts" && val.ProductQuantity !== 0)
.map((val) => {
return (
<div>
<div>
<div class="buyNowBtnDiv">
{localStorage.getItem("username") === "" ||
localStorage.length === 0 ? (
<div id="buyAddBtn">
</div>
) : (
<div id="buyAddBtn">
</div>
)}
</div>
</div>
</div>
);
})}

How to check if element exists in map() React

I have working code
const products = this.state.products.map((product, i) =>
product.fields.company.fields.slug === this.props.match.params.slug ?
<Suspense key={i} fallback={<div>Loading...</div>}>
<ProductListItem id={i} key={i} product={product} />
</Suspense>
: null)
return(
<div className="partner-details" style={partnerD}>
<div className="container-xl">
<Button type="button" className="btn btn-secondary" onClick={this.props.history.goBack}>
<i className="fa fa-arrow-left"></i> Get back
</Button>
<ul>
<div className="product-item">
{products}
</div>
</ul>
</div>
</div>
)
But the problem is if product.fields.company.fields.slug (company.fields.slug) does not exist my code crashes.
How can I add extra ternary operator to check if it product.fields.company exist before execute this product.fields.company.fields.slug === this.props.match.params.slug
Thanks!
if your environment has support for optional chaining you can do this
product?.fields?.company?.fields?.slug === this.props.match.params.slug ? .. : ..
otherwise you need to check that each field is truthy
product && product.fields && product.fields.company && product.fields.company.fields && product.fields.company.fields.slug === this.props.match.params.slug ? .. : ..
Use optional-chaining ( Babel plugin )
product.fields?.company?.fields?.slug
Or make use of the || operator :
(((product.fields || {}).company || {}).fields || {}).slug
And consider wrapping your compoennt in an error boundary so your app won't crash when there's this kind of errors.
In line 2 you can do:
(product && product.fields && product.fields.company && product.fields.company.fields && product.fields.company.fields.slug && this.props && this.props.match && this.props.match.params && this.props.match.params.slug && product.fields.company.fields.slug === this.props.match.params.slug) ?
or use optional chaining.

IF inside a map arrow function

Why does the if in this example, cause my react component not to compile.
How would one put a if like this in the map function then?
{this.props.medication.map((object, i) => (
if(object.med_type){
<div>
<div className="col-sm-6 col-md-6">{object.item.description}</div>
<div className="col-sm-6 col-md-6">{(object.med_assigneddate !== '' && object.med_assigneddate !== null) ? object.med_assigneddate : 'N/A'}</div>
</div>
}
))}
Arrow functions can have, on the right-hand side of the => symbol either:
A block
A statement (which gets an implicit return ahead of it)
If you want an if statement with its own block, you need to write the function body as a block and explicitly include the return statement.
(object, i) => {
if (object.med_type) {
return (
<div>
<div className="col-sm-6 col-md-6">{object.item.description}</div>
<div className="col-sm-6 col-md-6">{(object.med_assigneddate !== '' && object.med_assigneddate !== null) ? object.med_assigneddate : 'N/A'}</div>
</div>
);
}
}
It could be better filter first and then use the map. You have to return something from map scope. For sample:
{this.props.medication.filter(object => (object.med_type)).map((object, i) => (
return (
<div>
<div className="col-sm-6 col-md-6">{object.item.description}</div>
<div className="col-sm-6 col-md-6">{(object.med_assigneddate !== '' && object.med_assigneddate !== null) ? object.med_assigneddate : 'N/A'}</div>
</div>);
))}

Categories