I would like to stop the loop inside bedsAssign.map if row.id is not equal to u.tenant_id but putting break; doesn't work.
{tenants.map((row) =>
bedsAssign.map(
(u) =>
row.id !== u.tenant_id && (
<MenuItem key={row.id} value={row.id}>
{row.fullName}
</MenuItem>
break; --> not working
)
)
)}
You can add filter before map to remove all bedsAssign items which are not matched with current row.id
{
tenants.map((row) =>
bedsAssign
.filter((u) => row.id !== u.tenant_id)
.map((u) => (
<MenuItem key={row.id} value={row.id}>
{row.fullName}
</MenuItem>
))
)
}
If you want to break the loop, you can try to use some or find with a proper return for map
{
tenants.map((row) => {
const isAssigned = bedsAssign.some((u) => row.id !== u.tenant_id)
return isAssigned ? (<MenuItem key={row.id} value={row.id}>
{row.fullName}
</MenuItem>) : null
})
}
You can not break any array methods like forEach, filter, map etc. If you encounter a scenario where you want your loop to break then you should use traditional for loop.
use a filter instead of map for bedsAssign:
{tenants.map((row) =>
bedsAssign.filter(
(u) =>
row.id !== u.tenant_id && (
<MenuItem key={row.id} value={row.id}>
{row.fullName}
</MenuItem>
)
)
)}
the filter is going to only fill in the items that are meeting the condition you want.
EDIT: I noticed that you want to break once condition is met, this would work in this case:
{tenants.map((row) =>
for(let i of bedsAssign){
if(row.id !== i.tenant_id && (
<MenuItem key={row.id} value={row.id}>
{row.fullName}
</MenuItem>
)){
break
}
}
)
)}
Related
I have passwords array, I want to display those passwords - each password has a resource which should be displayed once as a title
So:
take resource as a title:
resource1: - password1 - password2 - password0,
resource2: - password4 - passwords5,
resource3: - password6 - password7 - password8 - password9
this.state.passwords && this.state.passwords.map((item, index) => {
return (
<>
{item[index] !== item[index + 1] && ( //here I am trying to do this logic
<Nav.Item><div className="sidebar-heading-secrets">{item.resource}</div></Nav.Item>
)}
<span>We render data here</span>
</>
)
})
}``
You are missing key in map. Use React.Fragment and supply a key
this.state.passwords && this.state.passwords.map((item, index) => {
return (
<React.Fragment key={index}>
{item[index] !== item[index + 1] && ( //here I am trying to do this logic
<Nav.Item><div className="sidebar-heading-secrets">{item.resource}</div></Nav.Item>
)}
<span>We render data here</span>
</React.Fragment>
)
})
}``
I want to render a JSX with some condition being true and map through an array.
below is the code,
{this.props.variables &&
this.props.variable.map((variable, index) => {
let element;
if (variable.anchor) {
element = document.querySelector(variable.anchor);
}
this.box_ref.current && element && (// error here
<Childcomponent
element1={this.box_ref.current}
anchor={variable.anchor}
/>)
}
}
)
}
There is an error saying that the expression is not an assignment or a call. how can I fix it? thanks.
You need to provide a return value for #Array.map callback.
Also, you should provide unique keys to React elements within an array:
<>
{this.props.variables &&
this.props.variable.map((variable, index) => {
let element;
if (variable.anchor) {
element = document.querySelector(variable.anchor);
}
// v Add return statement
return (
this.box_ref.current &&
element && (
<Childcomponent
key={index}
element1={this.box_ref.current}
anchor={variable.anchor}
/>
)
);
})}
</>
I'm working inside a functional React component and I'm trying to render a 'Card' component with a conditional onClick based on the member's typename. A card should be clickable if its typename is 'Bundle' or 'LegacyArticle'. Any other typename should not have an onClick property.
I'm having trouble finding an efficient way to apply an onClick to a card without having a conditional with a bunch of lines of repeated code, (the code that would essentially be nested children of the 'Card' component).
So far, I've been able to render it conditionally from a function. This allows my return statement to have better readability but there is still a big chunk of code that gets repeated, and I want to find a way to reduce that.
return (
<div css={cards}>
{members && members.map((member, index) => (
renderCard(member, index)
))}
</div>
);
const renderCard = (member, index) => {
const isClickable = member.__typename === 'Bundle' || member.__typename === 'LegacyArticle';
if (isClickable) {
return <Card key={index} css={card} onClick={() => onCardClick(member)}>
{(member.__typename !== 'LessonSpark' &&
schemas[member.__typename].image(member)) &&
(<CardImage src={schemas[member.__typename].image(member)} />)}
<CardBlock css={cardType}>
{member.label || schemas[member.__typename].typename}
</CardBlock>
<CardBlock css={cardTitleStyle}>
{_truncate(schemas[member.__typename].title(member), 60)}
</CardBlock>
</Card>
} else {
return <Card key={index} css={card}>
{(member.__typename !== 'LessonSpark' &&
schemas[member.__typename].image(member)) &&
(<CardImage src={schemas[member.__typename].image(member)} />)}
<CardBlock css={cardType}>
{member.label || schemas[member.__typename].typename}
</CardBlock>
<CardBlock css={cardTitleStyle}>
{_truncate(schemas[member.__typename].title(member), 60)}
</CardBlock>
</Card>
}
};
As you can see, <Card> has children nested, and it's a lot of lines of code being repeated when essentially, the only difference is one has an onClick and one doesn't.
Any ideas on how I could possibly reduce this code and find a clean way to apply an onClick conditionally?
You can basically use DRY principle by only changing the unique / custom parts. So in this case the only difference i could see between the if and else statements was the onClick, so you can instead put the conditional there, if you want an onClick, in this case use a ternary or you could use &&.
const renderCard = (member, index) => {
const typename = member.__typename;
const isClickable = typename === 'Bundle' || typename === 'LegacyArticle';
const schema = schemas[typename];
const image = schema.image(member);
const cardContents = (typename !== 'LessonSpark' &&
image) &&
(<CardImage src={image} />);
return (<Card key={index} css={card} onClick={ isClickable ? () => onCardClick(member) : undefined}>
{cardContents}
<CardBlock css={cardType}>
{member.label || schema.typename}
</CardBlock>
<CardBlock css={cardTitleStyle}>
{_truncate(schema.title(member), 60)}
</CardBlock>
</Card>);
}
In addition to that, you can save the values from function calls and from properties of objects so that a) the code is easier to read/follow, and b) the code is a bit more optimized, since it is not doing unnecessary extra function calls.
One way to accomplish this is by adding the condition inside your Card onClick prop:
const isClickable = member.__typename === 'Bundle' || member.__typename === 'LegacyArticle';
return <Card key={index} css={card} onClick={isClickable ? () => onCardClick(member): null}>
{(member.__typename !== 'LessonSpark' &&
schemas[member.__typename].image(member)) &&
(<CardImage src={schemas[member.__typename].image(member)} />)}
<CardBlock css={cardType}>
{member.label || schemas[member.__typename].typename}
</CardBlock>
<CardBlock css={cardTitleStyle}>
{_truncate(schemas[member.__typename].title(member), 60)}
</CardBlock>
</Card>
Put onClick into an object and use prop spread.
const renderCard = (member, index) => {
const typename = member.__typename;
const maybeOnClick = typename === 'Bundle' || typename === 'LegacyArticle' ?
{ onClick: () => onCardClick(member) } : {};
const schema = schemas[typename];
const image = schema.image(member);
const cardContents = (typename !== 'LessonSpark' &&
image) &&
(<CardImage src={image} />);
return (<Card key={index} css={card} {...maybeOnClick}>
{cardContents}
<CardBlock css={cardType}>
{member.label || schema.typename}
</CardBlock>
<CardBlock css={cardTitleStyle}>
{_truncate(schema.title(member), 60)}
</CardBlock>
</Card>);
}
I am wanting to add after every 3rd .map item I am wondering if anyone knows of the correct way to do so, As if statements don't work and I am unsure how to achieve this result.
<Grid container spacing={3}>
{items.map(item => (
<MediaCard title={item.title} link={item.url} pic={item.image} category={item.category} tweet={item.TweetIDs}/>
))}
<GoogleAds />
</Grid>
I tried to put the if statement in the MediaCard function however realized that was wrong due to I need it to run as the items.map runs.
\
There are two different ways to achieve that. To get the third element, use the modulo % operator. It returns the rest obtained by dividing the number.
First you can use the filter function before the map function:
{items.filter((item, index) => index % 3 === 2)
.map(item => (
<MediaCard />)}
Or return false in map, which will lead to no rendering.
items.map((item, index) => (
index % 3 === 2 && <MediaCard />)}
Hope this helps. Happy coding.
The second parameter of map is the index of the item. So you could do:
<Grid container spacing={3}>
{
items.map((item, index) => (
<>
<MediaCard title={item.title} link={item.url} pic={item.image} category={item.category} tweet={item.TweetIDs}/>
{
((index + 1) % 3 === 0) && <GoogleAds />
}
</>
))
}
</Grid>
<Grid container spacing={3}>
{items.map((item, index) => {
if ((index + 1) % 3 === 0) {
return (
<MediaCard title={item.title} link={item.url} pic={item.image} category={item.category} tweet={item.TweetIDs} />
)
}
else {
return null;
}
})}
<GoogleAds />
</Grid>
I'm creating a table by mapping my data , I'm trying to create a TableSortLable , but I only want to enable the users to sort by the first two columns .
{
Columns.map(c,index => {
return (
<TableCell key={c.key} component="th" padding="checkbox">
<TableSortLabel
active={props.brokersListOrderByColumn === c.key}
direction={props.brokersListSortOrder}
onClick={() => props.setOrderBy(c.key)}>
{c.label}
</TableSortLabel>
</TableCell>
)
})
}
I was thinking on using the onClick event, and to enable it only when its the first or second column . I tried something like:
{(index === 1 || index ===2) && onClick={() => props.setOrderBy(c.key)}}>
Or conditionally setting the onClick value , but both didn't work .
I've also tried conditionally setting the TableSortOrder :
<TableCell key={c.key} component="th" padding="checkbox">
{(index === 1 || index === 2) && <TableSortLabel
active={props.brokersListOrderByColumn === c.key}
direction={props.brokersListSortOrder}
onClick={() => props.setOrderBy(c.key)}>
{c.label}
</TableSortLabel>}
{(index !== 1 && index !== 2) && c.label}
</TableCell>
But it complains c is undefined
Syntax error. You should write parameters in brackets for functors. Like this
Columns.map((c, index) => {...
Otherwise engine will try to find (RHS) variable c (expected as function).
You didnt init such variable and get this
But it complains c is undefined .
Try onClick={(index === 1 || index === 2) ? () => props.setOrderBy(c.key) : null}
Try to give something like
onClick={
() => (index === 1 || index === 2) && props.setOrderBy(c.key)
}
Maybe you can just add check inside handler?
onClick={() => {
if((index === 1 || index ===2)) {
props.setOrderBy(c.key)}
}
}}
You can also extract array function for breivity:
const onClick = () => {
if((index === 1 || index ===2)) {
props.setOrderBy(c.key)}
}
}
....
onClick={onClick}>