JSX map inside a map is it possible? - reactjs

I'm trying to map over a map in JSX but the second inner map doesn't render why?
{food.map((item: ItemsShape, index: number) => {
return (
<div key={`${index}`}>
<div>{item.Quantity}</div>
<div>{item.Name}</div>
{item.Options && <div>{JSON.stringify(item.Options)}</div>} // <= this shows al the options
{item.Options &&
item.Options.map((option: any) => {
<div>OPTION {option.Name}</div>;
})} // <= This doesnt even render why?
</div>
);
})}

You missed return
{food.map((item: ItemsShape, index: number) => {
return (
<div key={`${index}`}>
<div>{item.Quantity}</div>
<div>{item.Name}</div>
{item.Options && <div>{JSON.stringify(item.Options)}</div>} // <= this shows al the options
{item.Options &&
item.Options.map((option: any) => {
return (<div>OPTION {option.Name}</div>);
})}
</div>
);
})}

Related

reusing array.map() in React.js

I can't find an answer in "many similar questions", sorry I'm new to react.
I have the following code inside return of my sfc that works/renders fine:
{data && allToDos && completed === 'all' && data.map(data => {
key++;
return (
<div key={key}>
<h2>{data.title}</h2>
<p className="apart">
Nr: {data.id} <span>Status: {!data.completed && <span>Not </span>}completed</span>
</p>
<h3>User: {data.userId}</h3>
<br/><hr/><br/>
</div>
);
});}
Now, I have 3 different options for completed and in each case i want to render different set of data, so i have isolated the data.map(data => {/*code*/}) into a separate function inside the same component,like that:
const dataMap = () => {
data.map(data => {
key++;
return (
<div key={key}>
<h2>{data.title}</h2>
<p className="apart">
Nr: {data.id} <span>Status: {!data.completed && <span>Not </span>}completed</span>
</p>
<h3>User: {data.userId}</h3>
<br/><hr/><br/>
</div>
);
});
}
and then i passed that function inside return like that:
{data && allToDos && completed === 'all' && dataMap()}
and nothing is rendered, but no error messages either.
You're not returning from dataMap() function it returns undefined .
try this
const dataMap = () => {
return data.map(data => {
key++;
return (
<div key={key}>
<h2>{data.title}</h2>
<p className="apart">
Nr: {data.id} <span>Status: {!data.completed && <span>Not </span>}completed</span>
</p>
<h3>User: {data.userId}</h3>
<br/><hr/><br/>
</div>
);
});
}

Getting undefined error when trying to print sum of an element of an array in react ts

Getting object is possibly 'undefined' on order.reduce line.
Trying to print sum of all the amounts after printing all the amount.
<div>
{orders.map(({ id, totalAmount }) => {
return (
<div key={id}>
<div>{totalAmount}</div>
</div>
)
})}
Total: {
orders.reduce(
(t, k) => (t + k.totalAmount),
0
)
}
</div>
That is happening because TypeScript thinks the array orders array can be undefined. To fix this, you can make a check like this
const Component = () => {
return (
<div>
{orders && (
<div>
{orders.map(({ id, totalAmount }) => {
return (
<div key={id}>
<div>{totalAmount}</div>
</div>
);
})}
Total: {orders.reduce((t, k) => t + k?.totalAmount, 0)}
</div>
)}
</div>
);
};

How to return React component inside mapping

I just can't figure out the syntax mistake here, but my React components won't render. What am I doing wrong?
return (
shouldShow && (
<div>
{this.props.photos.map(({ url }) => {
return (
this.state.expanded
? <ImageGallery passedProp={url} />
: <AnotherComponent passedProp={url}
)
})}
</div>
)
);
I get the error:
JSX attributes must only be assigned a non-empty expression
EDIT updated full code as requested:
showGallery = () => {
const shouldShow = this.props.photos.length > 0;
return (
shouldShow && (
<div>
{this.props.photos.map(({ url }) => {
return (
this.state.expandedThumbnail
? <ImageGallery imageUrl={urlurlurl}/>
: <button
key={url}
onClick={this.doThis}
>
<img
src={url}
/>
</button>
)
})}
</div>
)
);
};

No render elements from array - ReactJS

Project based on Typescript vs ReactJS.
This is render code :
return (
<div ref={this.myRef} style={this.state.myStyle} >
{this.state.sections.map((sectionsItem: AppI.SectionI) => {
if (this.state.activeSection === sectionsItem.name) {
console.log("TEST :", sectionsItem.elements );
sectionsItem.elements.map((element: React.ReactElement<any>, index: number) => {
return <span key={index} >{element}</span>;
});
}
})}
</div>
);
In debugger I can see that 'elements' are not empty but it doesn't render in html.
Any suggestion ?!
You need an extra return statement:
Change: sectionsItem.elements.map to return sectionsItem.elements.map:
Your inner .map returns elements but the outer .map has no return statement:
return (
<div ref={this.myRef} style={this.state.myStyle} >
{this.state.sections.map((sectionsItem: AppI.SectionI) => {
if (this.state.activeSection === sectionsItem.name) {
console.log("TEST :", sectionsItem.elements );
return sectionsItem.elements.map((element: React.ReactElement<any>, index: number) => {
return <span key={index} >{element}</span>;
});
}
})}
</div>
);

How do you toggle filtered list items inside of a div in React?

I'm building a React component that shows a filtered list of items in a div when users click on a button. Only the items within that div should be displayed on click. For some reason, though, the lists for every section are being toggled.
What am I doing wrong?
Here is my code: https://codesandbox.io/s/6yr0jzlpwn
Simply you can just define a specific value for each button then pass it to state
<div>
<h1>{this.state.title}</h1>
<div>
<button value={'1'} onClick={this.toggleWords}>肉</button>
{this.state.showWords === '1' && (
<ul>
{this.state.list.filter(function(word) {
return word[1] === "肉";
}).map(function (word) {
return <li>{word}</li>;
})}
</ul>
)}
</div>
<div>
<button value={'2'} onClick={this.toggleWords}>茶</button>
{this.state.showWords === '2' && (
<ul>
{this.state.list.filter(function(word) {
return word[1] === "茶";
}).map(function(word) {
return <li>{word}</li>;
})}
</ul>
)}
</div>
<div>
<button value={'3'} onClick={this.toggleWords}>日</button>
{this.state.showWords === '3' && (
<ul>
{this.state.list.filter(function(word) {
return word[0] === "日";
}).map(function(word) {
return <li>{word}</li>;
})}
</ul>
)}
</div>
</div>
In toggleWords function
toggleWords(e) {
const clickedButton = e.target.value;
if(clickedButton !== this.state.showWords){
this.setState({ showWords: clickedButton })
}else{
this.setState({ showWords: '' }) // handle close list if double click
}
}
In case if you want to expand two sections at once you need to change showWords state to be an array then use indexOf method to extend the section
<div>
<h1>{this.state.title}</h1>
<div>
<button value={'1'} onClick={this.toggleWords}>肉</button>
{this.state.showWords.indexOf('1') !== -1 && (
<ul>
{this.state.list.filter(function (word) {
return word[1] === "肉";
}).map(function (word) {
return <li>{word}</li>;
})}
</ul>
)}
</div>
<div>
<button value={'2'} onClick={this.toggleWords}>茶</button>
{this.state.showWords.indexOf('2') !== -1 && (
<ul>
{this.state.list.filter(function (word) {
return word[1] === "茶";
}).map(function (word) {
return <li>{word}</li>;
})}
</ul>
)}
</div>
<div>
<button value={'3'} onClick={this.toggleWords}>日</button>
{this.state.showWords.indexOf('3') !== -1 && (
<ul>
{this.state.list.filter(function (word) {
return word[0] === "日";
}).map(function (word) {
return <li>{word}</li>;
})}
</ul>
)}
</div>
</div>
Then in toggleWords function will delete the value from array if exist else it will add it
toggleWords(e) {
const clickedButton = e.target.value;
if (this.state.showWords.indexOf(clickedButton) !== -1) { // deleting the value from array if exist
this.setState(prevState => ({ showWords: this.state.showWords.filter(d => d !== clickedButton) }))
} else {
this.setState(prevState => ({ showWords: [...prevState.showWords, clickedButton] }))
}
}

Resources