Reading nested array and display items using React - reactjs

I was unable to populate the with the correct array information. This is now working with the fix below.
Here is the corrected file.
renderComments(){
if (this.props.selectedDish != null) {
const commentList = this.props.selectedDish.comments;
return (
<div>
<h4>Comments</h4>
{commentList.map((comment) => {
return (
<ul className="list-unstyled" >
<li>
<p>{comment.comment}</p>
<p> -- {comment.author}{" "}
{Intl.DateTimeFormat("en-US",{
month: "short",
day: "2-digit",
year: "numeric"}).format(new Date(comment.date))}
</p>
</li>
</ul>
);
})};
</div>
);
} else {
return (
<div></div>
);
}
}
Thank you sava128

You should assign comments like you did with dish.name and dish.description
try:
renderComments() {
const dish = this.props.selectedDish;
if (dish) {
const commentList = dish.comments;
console.log("test2", commentList);
return (
<div>
<h4>Comments</h4>
<ul className="list-unstyled">
{commentList.map((comment) => {
return (
// list items here
)
})}
</ul>
</div>
);
} // else here
}

Related

toggle is not toggling element but it's collapsing element in navigation

I'm creating navigation for mobile devices. Everything works, but when I'm trying to open third level of navigation, it doesn't open, but collapses previous level. I dont know what to do and I'm pretty dissapointed, because it seems like easy thing and I feel like dumb. Someone have any tips please? :(
function MobileCategoriesLinks(props: MobileLinksProps) {
const { data } = useCollectionsQuery();
const { level = 0, onItemClick } = props;
const handleItemClick = (item: any) => {
if (onItemClick) {
onItemClick(item);
}
};
const linksList = data?.collections.items.map((department, index) => {
let item;
if(department.parent?.id === "1") {
const renderItem: RenderItemFn = ({ toggle, setItemRef, setContentRef }) => {
let arrow = null;
let subLinks = null;
let linkOrButton = null;
let link = "/" + department.children
if(department.children?.length) {
arrow = (
<button className="mobile-links__item-toggle" type="button" onClick={toggle}>
<ArrowRoundedDown12x7Svg className="mobile-links__item-arrow" />
</button>
);
}
let depChild = department.children?.map((name) => {
let x = name.name
let link = "/" + name.slug
let child = name
let c = child.children
if(child.children?.length) {
let thirdChild = child.children?.map((item, index) =>{
return item.name
})
let thirdChildSlug = child.children?.map((item, index) =>{
return item.slug
})
arrow = (
<button className="mobile-links__item-toggle" type="button" onClick={toggle}>
<ArrowRoundedDown12x7Svg className="mobile-links__item-arrow" />
</button>
);
subLinks = (
<div className="mobile-links__item-sub-links" ref={setContentRef}>
<ul className="mobile-links mobile--links--level--3">
<li>
<div className="mobile-links__item">
<div className="mobile-links__item-title">
{thirdChild}
</div>
</div>
</li>
</ul>
</div>
)
if(child.children?.length) {
linkOrButton = (
<AppLink
href={"/" + child.slug}
className="mobile-links__item-link"
onClick={() => handleItemClick(link)}
>
{child.name}
</AppLink>
)}
return (
<li>
<div className="mobile-links__item" ref={setItemRef}>
<div className="mobile-links__item-title">
<AppLink
href={"/" + child.slug}
className="mobile-links__item-link"
onClick={() => handleItemClick(link)}
>
{name.name}
</AppLink>
{arrow}
</div>
{subLinks}
</div>
</li>
)}
return (
<li>
<div className="mobile-links__item">
<div className="mobile-links__item-title">
{x}
</div>
</div>
</li>
);
}
)
subLinks = (
<div className="mobile-links__item-sub-links" ref={setContentRef}>
<ul className="mobile-links mobile--links--level--2">
{depChild}
</ul>
</div>
)
if(department.children) {
linkOrButton = (
<AppLink
href={"/" + department.slug}
className="mobile-links__item-link"
onClick={() => handleItemClick(link)}
>
{department.name}
</AppLink>
)} else {
linkOrButton = (
<button
type="button"
className="mobile-links__item-link"
onClick={() => handleItemClick(link)}
>
{department.name}
</button>
)
}
return (
<div className="mobile-links__item" ref={setItemRef}>
<div className="mobile-links__item-title">
{linkOrButton}
{arrow}
</div>
{subLinks}
</div>
);
};
item = <Collapse toggleClass="mobile-links__item--open" render={renderItem} />;
}
return <li key={index}>{item}</li>
}
);
return ( <ul className={`mobile-links mobile-links--level--1`}>
{linksList}
</ul>
);
}
export default withApollo(MobileCategoriesLinks)

Where is the missing key for my child comp?

I've been getting a "Each child in a list should have a unique key prop" error. I've read up on the documentation and put keys in, but no luck. Not sure what I'm misunderstanding!
blogPosts is imported from a context.
The ids being called as keys are unique (POSTID1, POSTID2, ...etc).
Got rid of some classnames for better readability.
const topicPosts = blogPosts.filter((post)=>post.topic.toLowerCase()===topic);
const handleLoadMore = () => {
const newIndex = articleIndex + 5 > topicPosts.length ? topicPosts.length : articleIndex + 5;
setArticleIndex(newIndex);
}
return (
<section onClick={handleOutsideClick}>
<div>
<section>
<h1>{topic}</h1>
{
topicsData.map((topicData)=> topicData.name.toLowerCase()===topic && <p key={topicData.id}>{topicData.intro}</p>)
}
</section>
<div>
<section>
<div>
{
topicPosts.slice(0,3).map((post)=>{
const { id } = post;
return (
<TopicPagePost key={id} {...post}/>
)
})
}
</div>
<div className={topicPosts.length>3 ? `subpage-articles` : `display-none`}>
{
topicPosts.slice(3,articleIndex).map((post, index)=>{
const { id } = post;
return (
<>
<TopicPagePost key={id} {...post}/>
{
index%4===0 && <div key={index} className="subpage-main-ad">
Ad placement here
</div>
}
</>
)
})
}
</div>
<button type="button" onClick={handleLoadMore}>Load more articles</button>
</section>
<aside>
<SubscribeBlock/>
<div>
Ad placement here
</div>
</aside>
</div>
</div>
</section>
)
That is because you need to add a key to the first element returned from the map, in this case <>.
To do that, you need to replace <> with a <Fragment> instead, so you can add a key directly to it:
import React, { Fragment } from "react"
{topicPosts.slice(3,articleIndex).map((post, index) => {
const { id } = post;
return (
<Fragment key={id}>
<TopicPagePost {...post}/>
{index%4===0 && (
<div className="subpage-main-ad">
Ad placement here
</div>
)}
</Fragment>
)
})}

conditional rendering using an anonymous function (React)

I am trying to get my head around condtional rendering and have started trying to implment this with a anonymous function.
pseudo code
if(statement)
render this
else
render something else
The condition works if the Boolean is set to isLoggedin = true but if false it throws
Error: DisplayUserAcountDetails(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
My actual code
render() {
const isLoggedIn = false;
if (isLoggedIn)
return (
<div>
{(() => {
if (isLoggedIn) {
return (
<ul>
{this.state.AccountDetails &&
this.state.AccountDetails.map(function(
AccountDetails,
index
) {
return (
<div className="jumbotron">
<h3>Account Details</h3>
<li> Email: {AccountDetails.Email}</li>
<li> Name: {AccountDetails.NameOfUser}</li>
<li>
{" "}
Contact Number: {AccountDetails.ContactNumber}{" "}
</li>
<li>
<Link to="/profile-update-account-details">
<button>Update Account Details</button>
</Link>
</li>
</div>
);
})}
</ul>
);
} else {
return (
<div>
<div>otherCase</div>
<h1>Not there</h1>
</div>
);
}
})()}
</div>
);
}
Why is this throwing an error when one is rendered but the other loads fine? Is there some logic that I am missing?
First solution:
render() {
const isLoggedIn = false;
if (!isLoggedIn) {
return (
<div>
<div>otherCase</div>
<h1>Not there</h1>
</div>
);
}
return (
<ul>
{this.state.AccountDetails &&
this.state.AccountDetails.map(function(AccountDetails, index) {
return (
<div className="jumbotron">
<h3>Account Details</h3>
<li> Email: {AccountDetails.Email}</li>
<li> Name: {AccountDetails.NameOfUser}</li>
<li> Contact Number: {AccountDetails.ContactNumber} </li>
<li>
<Link to="/profile-update-account-details">
<button>Update Account Details</button>
</Link>
</li>
</div>
);
})}
</ul>
);
Second solution:
render() {
const isLoggedIn = false;
return (
<>
{isLoggedIn ? (
<ul>
{this.state.AccountDetails &&
this.state.AccountDetails.map(function(AccountDetails, index) {
return (
<div className="jumbotron">
<h3>Account Details</h3>
<li> Email: {AccountDetails.Email}</li>
<li> Name: {AccountDetails.NameOfUser}</li>
<li> Contact Number: {AccountDetails.ContactNumber} </li>
<li>
<Link to="/profile-update-account-details">
<button>Update Account Details</button>
</Link>
</li>
</div>
);
})}
</ul>
) : (
<div>
<div>otherCase</div>
<h1>Not there</h1>
</div>
)}
</>
);
}
1) You are missing curly braces { } of the if else statement.
2) You should check out the ternary operator in JavaScript.
I'm pretty sure you are missing a ELSE statement.
Have a look:
render() {
const isLoggedIn = false;
if (isLoggedIn)
return (
<div>
{(() => {
if (isLoggedIn) {
return (
<ul>
{this.state.AccountDetails &&
this.state.AccountDetails.map(function(
AccountDetails,
index
) {
return (
<div className="jumbotron">
<h3>Account Details</h3>
<li> Email: {AccountDetails.Email}</li>
<li> Name: {AccountDetails.NameOfUser}</li>
<li>
{" "}
Contact Number: {AccountDetails.ContactNumber}{" "}
</li>
<li>
<Link to="/profile-update-account-details">
<button>Update Account Details</button>
</Link>
</li>
</div>
);
})}
</ul>
);
} else {
return (
<div>
<div>otherCase</div>
<h1>Not there</h1>
</div>
);
}
})()}
</div>
);
else
{
return (null)
}
}

Looping through object and using map doesn't return jsx

I am trying to loop through object of objects and using map to list the item and I am getting this object from redux. I can console.log the value but jsx returns nothing. I tried removing {} and return and using () only but still it is not rendering anything.
My posts object looks like
posts = { 1: {id: 1, title: "Hello world"} }
Component.js
renderList(){
const { posts } = this.props;
Object.keys(posts).map(key => {
console.log(`${key} and ${posts[key].title}`);
return (
<li key={key} className="list-group-item">
{posts[key].title}
</li>
);
});
}
render(){
return (
<div>
<h2>Posts</h2>
<ul className="list-group">{this.renderList()}</ul>
</div>
);
}
I can't figure out what I am doing wrong.
Your renderList method does not have a return statement.
Depending on if your version of React you can either return an array here or you need to wrap it in a div (or in this case put the ul into it).
renderListOnReact16(){
const { posts } = this.props;
return Object.keys(posts).map(key => {
console.log(`${key} and ${posts[key].title}`);
return (
<li key={key} className="list-group-item">
{posts[key].title}
</li>
);
});
}
renderOnReact16(){
return (
<div>
<h2>Posts</h2>
<ul className="list-group">{this.renderList()}</ul>
</div>
);
}
renderListOnReact15(){
const { posts } = this.props;
return (
<ul className="list-group">
{Object.keys(posts).map(key => {
console.log(`${key} and ${posts[key].title}`);
return (
<li key={key} className="list-group-item">
{posts[key].title}
</li>
);
})}
);
}
renderOnReact16(){
return (
<div>
<h2>Posts</h2>
{this.renderList()}
</div>
);
}

convert React-Js function to class

I tried to convert react js function to class but I didn't know how to convert it completely please look at this function and convert it for me correctly.
original function
code :var MailboxList = React.createClass({render: function() {
var mailbox_list = this.props.mailboxes.map(function(mailbox) {
return (
<li className="list-group-item"
key={mailbox.id}
onClick={this.props.onSelectMailbox.bind(null, mailbox.id)}>
<span className="badge">
{mailbox.emails.length}
</span>{mailbox.name}</li>);}.bind(this));
return (
<divclassName="col-md-2">
<ul className="mailboxes list-group">
{mailbox_list}</ul>
</div>);
}});
I would recommend using the most recent way to build component with babel 6.
As a Functions
export default function MailboxList({ mailboxes }) {
const mailbox_list = mailboxes.map((mailbox) =>
(
<li className="list-group-item"
key={mailbox.id}
onClick={this.props.onSelectMailbox.bind(null, mailbox.id)}
>
<span className="badge">
{mailbox.emails.length}
</span>{mailbox.name}</li>
));
return (
<div className="col-md-2" >
<ul className="mailboxes list-group">
{mailbox_list}</ul>
</div>
);
}
As a Class
export default class MailboxList extends React.Component {
renderMailboxList = () => {
return (
this.props.mailboxes.map((mailbox) => (
<li className="list-group-item"
key={mailbox.id}
onClick={this.props.onSelectMailbox.bind(null, mailbox.id)}
>
<span className="badge">
{mailbox.emails.length}
</span>
{mailbox.name}
</li>
))
)
}
render() {
return (
<div className="col-md-2" >
<ul className="mailboxes list-group">
{this.renderMailboxList}</ul>
</div>
);
}
}

Resources