Render from object values - React js - javascript

I have this response object from an api, and I want to loop it and render it as if it was a normal array, how can I render tshirt, jeans and furniture? I will not like to render the value of sneakers, Any suggestion?
const items = {
tshirt: "Model TS",
jeans: "ModelXW",
sneakers: "indcdsc54",
furniture: "Table31S"
};
{Object.keys(items).map=>{i =>
<Card>
{items[key]}
</Card>
}
}

Try this one implementation line:
{Object.entries(items).filter(v => v[0] !== 'sneakers').map((v, idx) => <Card key={idx}>v[1]</Card>)}

You can read properties of an object using dynamic key: objectName[keyName]:
{
Object.keys(items).map(key => <Card key={key}>{items[key]}</Card>)
}
and to filter out sneakers:
{Object.keys(items).filter(key => key !== 'sneakers').map((key) => (
<Card key={key}>{items[key]}</Card>
))}

Instead of multiple loops, add an if condition to your code:
Object.keys(items).map(key => {
if (key != 'sneakers') {
return(<Card>{items[key]}</Card>);
}
});

We can use destructuring and it is definitely more readable.
const { sneakers, ...rest } = items;
Object.keys(rest).map((item, id) => {
<Card key={id}>
{item}
</Card>
}
);

Related

Avoid infinite loop when updating

I have to update a state of items and see the changes right away. When I'm doing this below, I get an infinite loop.
useEffect(() => {
const playersInFight = gameData.characters.filter((x) =>
fightData.currentPositionInfoDTOS.some((y) => y.entityId == x.id)
);
let orderedCharacters = addPlayers(
playersInFight,
fightData.currentPositionInfoDTOS,
fightData.turnOrder
);
setAllCharacterCards(orderedCharacters);
}, [fightData, gameData, fightInfo, allCharacterCards, allCharacters]);
I have tried also like this:
useEffect(() => {
const playersInFight = gameData.characters.filter((x) =>
fightData.currentPositionInfoDTOS.some((y) => y.entityId == x.id)
);
let orderedCharacters = addPlayers(
playersInFight,
fightData.currentPositionInfoDTOS,
fightData.turnOrder
);
setAllCharacterCards(orderedCharacters);
}, [fightData, gameData, fightInfo, allCharacterCards, allCharacters]);
useEffect(() => {
setAllCharacterCards(allCharacterCards);
}, [allCharacterCards]);
And thanks to that I don't have an infinite loop, but to see the changes I have to refresh the page...
How can I solve this?
Update:
Here is my return:
return (
<section>
<div className="player-fight">
{allCharacterCards ? (
<div>
{allCharacterCards.map((c, idx) => {
return (
<li key={idx} className="player-fight-bottom__player-card">
<CardComponentPlayerCard
id={c.id}
name={c.name}
money={c.money}
health={c.health}
maxHealth={c.maxHealth}
mine={false}
description={c.description}
statuses={c.statuses}
image={c.photoPath}
/>
</li>
);
})}
</div>
) : (
<LoadingSpinner />
)}
</div>
</section>
);
To avoid infinite looping you need to remove allCharacterCards from useEffect dependency array.
useEffect(() => {
const playersInFight = gameData.characters.filter((x) =>
fightData.currentPositionInfoDTOS.some((y) => y.entityId == x.id)
);
let orderedCharacters = addPlayers(
playersInFight,
fightData.currentPositionInfoDTOS,
fightData.turnOrder
);
setAllCharacterCards([...orderedCharacters]);
}, [fightData, gameData, fightInfo, allCharacters]);
Explanation (after question edited)
setAllCharacterCards([...orderedCharacters]);
This should fix your problem.
Since allCharacterCards is an array of objects you need to use spread operator ... to let react know that you are updating state everytime with new values.
Read more about - Deep copy vs shallow copy.

How to update specific object value of an array in javascript

I have an array of objects, I did a map on that array now I want to change specific object values. I used onChange method inside map() function. It not working properly could someone please help me to achieve this problem solution.
thanks
localPreRoutingCall &&
localPreRoutingCall.map((item, index) => (
<>
<div className="pre-route-title">{item && item.field_title}</div>
<textarea
placeholder="Enter something"
className="pre-route-textarea"
value={item && item.value}
onChange={(e) => {
e.persist();
changeObjectValue(e.target.value, item);
}}
/>
<div className="pre-route-description">
{item && item.description}
</div>
</>
))
A function where I am updating object value
const changeObjectValue = (value, item) => {
console.log("## array", value);
let localArray = localPreRoutingCall;
var index = _.findIndex(localArray, { id: item.id });
localArray.splice(index, 1, { ...item, value: value });
setLocalPreRoutingCall(localArray);
};
Like said in the comments, you have to pass a key prop to what you're rendering so React knows what changes.
I don't see a reason for you to use the e.persist function when you're passing the value immediately.
import { Fragment } from "react";
localPreRoutingCall?.map((item, i) => (
<Fragment key={item.id}>
<div className="pre-route-title">{item.field_title}</div>
<textarea
placeholder="Enter something"
className="pre-route-textarea"
value={item.value}
onChange={(e) => changeObjectValue(e.target.value, i)}
/>
<div className="pre-route-description">
{item.description}
</div>
</Fragment>
))
You also didn't clone the localPreRoutingCall state array before changing its value.
Another reason why React won't know what changed.
const changeObjectValue = (value, i) => {
const localArray = [...localPreRoutingCall];
localArray[i].value = value;
setLocalPreRoutingCall(localArray);
};
One obvious problem I can see is that you aren't giving the mapped components keys.
<> can't be used in map because it can't be passed a key, so this would be an improvement
<React.Fragment key={item.id}>
Instead of using
localArray.splice(index, 1, { ...item, value: value });
Use
localArray[index].value = value

Render Component in Map.foreach

Im trying to render a component for every item in my Map Object, grouped is typed as
Map<string, Invite[]> | undefined
.map is not an option here, Property 'map' does not exist on type 'Map<string, PactInvite[]>'. Foreach is but this does not return the div or component. How can I render the items in a foreach?
const PendingInvitesView = (props: PendingInvitesProps) => {
const { refetchPactsProfiles, onClickPreviewProfile, grouped } = props
const { t } = useTranslation()
return (
<div className={styles['invite-section']}>
<Accent className={styles['invite-section-title']}>{t('agenda.invites.title')}</Accent>
<Space style={{ width: '100%' }} size="small" direction="vertical">
<>
{grouped?.forEach((element) => {
element.length > 1 ? (
<div>test</div>
) : (
<InviteCard
onClickPreviewProfile={onClickPreviewProfile}
refetchPactsProfiles={refetchPactsProfiles}
invite={element[0] as Invite}
/>
)
})}
</>
</Space>
</div>
)
}
You cannot render items using forEach because return value of this method is undefined.
I propose you convert the Map into array before you do rendering part. Then you should use map method.
Here's one example how to do it.

Drying up/refactoring a component nin ReactJs

I have this long-winded component which is passing many props. Is there a dryer way of passing this component to child?
Thanks.
let products;
if (!this.state.loading) {
products = this.state.products.map(product => (
<Product
description={product.description}
title={product.title}
originalRetailPrice={product.original_retail_price.formatted_value}
retailPrice={product.retail_price.formatted_value}
priceValue={product.retail_price.value}
discounted={product.discount}
imageURL={product.cover_image_url}
key={product.uuid}
uuid={product.uuid}
onClick={this.addToBagHandler}
/>
));
}
These are properties returned from an api call.
You just pass the whole product instead
let products;
if (!this.state.loading) {
products = this.state.products.map(product => (
<Product
product={product}
onClick={this.addToBagHandler}
/>
));
}
And inside Product you can access them like this:
const { description, title, discount } = this.props.product
You can destructure like this
let products;
if (!this.state.loading) {
products = this.state.products.map(({
description,title, original_retail_price,
retail_price, retail_price,discount,cover_image_url,
uuid}) =>
<Product
description={description}
title={title}
originalRetailPrice={original_retail_price.formatted_value}
retailPrice={retail_price.formatted_value}
priceValue={retail_price.value}
discounted={discount}
imageURL={cover_image_url}
key={uuid}
uuid={uuid}
onClick={this.addToBagHandler}/>
)}

React JS: Rendering object keys and its values

I am trying to render an objects key and value, however it just doesn't seem to work.
I have managed to display it in the console, but not the actual dom.
I am iterating through the object which has multiple entries.
What do I need to do to actually print out the values?
{attributes.map(items => {
{Object.keys(items).map((key) => {
console.log(key, items[key]);
})}
})}
Like this:
{attributes.map((items, index) => {
return (
<ul key={index}>
{Object.keys(items).map((key) => {
return (
<li key={key + index}>{key}:{items[key]}</li>
)
})}
</ul>
)
})}

Categories

Resources