Map and Sort Methods for component in React? - reactjs

Relatively new to React and trying to sort the mapped prop nearbyRestaurants alphabetically by place.name. Is there a way I can chain the sort method to the end of the map method to alphabetize the list?
export default function RestaurantList({nearbyRestaurants}) {
return (
<div>
<ul>
<li className="list-header">Restaurants</li>
{nearbyRestaurants.map((place) => (
<div>
<li>
<div>{place.name}</div>
<div>{place.vicinity}</div>
</li>
</div>
))}
</ul>
</div>
);
}

Sort the array before mapping it.
function sortAlphabetically(a,b){
return a.name.localeCompare(b.name)
}
export default function RestaurantList({nearbyRestaurants}) {
return (
<div>
<ul>
<li className="list-header">Restaurants</li>
{nearbyRestaurants.sort(sortAlphabetically).map((place) => (
<div>
<li>
<div>{place.name}</div>
<div>{place.vicinity}</div>
</li>
</div>
))}
</ul>
</div>
);
}

Related

How to anchor a component with prop?

I have a website that I used fixed menu options to anchor to the place I wanted ,below is a simple structure to demonstrate
mypage.jsx
<div className="mywork">
<TopbarWork menuOpen={menuOpen} setMenuOpen={setMenuOpen}/>
<MenuWork menuOpen={menuOpen} setMenuOpen={setMenuOpen}/>
<div className="sections">
<Product /> //origin
<Story workData={workData}/> //what I want to achieve
<Userflow workData = {workData}/>
<System workData={workData}/>
<FinalDesign workData={workData}/>
</div>
</div>
menu.jsx(click to go to the different anchors)
import './menu.scss'
export default function Menu({menuOpen,setMenuOpen}) {
return (
<div className={"menu " + (menuOpen && "active")}>
<ul>
<li onClick={()=>setMenuOpen(false)}>
Back
</li>
<li onClick={()=>setMenuOpen(false)}>
product
</li>
</ul>
</div>
)
}
Product.jsx(one of the components)
import { CheckCircle } from '#material-ui/icons';
import './product.scss'
export default function Product({workData}) {
return (
<div className="product" id="product"> //important
<div className="productLeft">
<div className="productIntro">
<p className="title">
{workData.title}
</p>
<p className="desc">
{workData.desc}
</p>
{workData.featured.map((feature)=>{
return(
<div className="featured">
<CheckCircle className="featuredIcon"/>
{feature.title}
</div>
)
})}
</div>
</div>
<div className="productRight">
<div className="item">
<img src="assets/desktop.jpeg" alt="" className="desktopImg" />
<img src={workData.productImg} alt="" className="productImg" />
</div>
</div>
</div>
)
}
So right now the problem is I have to pass "workData" into components , but after that if I click on the anchor, it would show Cannot read properties of undefined (reading 'workData') , I assume that I have to pass the workData too when I click on the anchor ?
But what's the right way to do that ?
EDIT
I tried using Link and history (react-router-dom) but failed , here's my code
menu.jsx
export default function MenuWork({menuOpen,setMenuOpen,workData}) {
console.log(workData)
const history = useHistory();
const handleClick = ()=>{
setMenuOpen(false)
history.push({
pathname:'/mywork#userflow',
state: { workData:workData}
})
}
return (
<div className={"menu " + (menuOpen && "active")}>
<ul>
<li onClick={()=>setMenuOpen(false)}>
Back
</li>
<li onClick={()=>setMenuOpen(false)}>
<Link to="#product">Product</Link>
</li>
<li onClick={()=>setMenuOpen(false)}>
<Link to={{
pathname:"/mywork#story",
state:{ workData:workData}
}}>Story</Link>
</li>
<li onClick={()=>handleClick()}>
userflow
</li>
</ul>
</div>
)
}
If I use Link and pass the state, it will return blank page without loading anything, and If I don't pass any state with Link , it will shows the same error as above.

React Cannot read property of undefined - Array.map (<anonymous>)

I am fetching data from api and importing the data in the WeatherData.js and passing it as a prop to SmallWeatherCard.js because I want to pass it to another component too later on.
when I do console.log(data) in SmallWeatherCard.js I can see the whole data in the console but when trying to map it I get an error "Cannot read property of undefined"
What am I doing wrong here?
all the code here: Codesanbox
import React from "react";
export const SmallWeatherCard = ({ data }) => {
return (
<div>
{data.properties.timeseries.map((i, index) => (
<div>
<ul key={index}>
<li> {i.data.next_6_hours.summary.symbol_code}
</li>
<li>
{Math.round(i.data.next_6_hours.details.air_temperature_min)}°
</li>
<li>|</li>
<li>
{Math.round(i.data.next_6_hours.details.air_temperature_max)}°
</li>
</ul>
</div>
))}
</div>
);
};
Your probably using this kinda api. So, the error is api doesn't always return all fields. For example in my case i.data.next_6_hours wasn't defined.
So, try something like this,
export const SmallWeatherCard = ({ data }) => {
console.log(typeof data);
return (
<div>
{data.properties.timeseries.map(
(i, index) =>
i.data.next_6_hours != null && (
<div>
<ul key={index}>
<li>
{Math.round(i.data.next_6_hours.details.air_temperature_min)}°
</li>
<li>|</li>
<li>
{Math.round(i.data.next_6_hours.details.air_temperature_max)}°
</li>
</ul>
</div>
)
)}
</div>
);
};
Using CodeSandbox.

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)
}
}

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>
);
}
}

react dom traverself or parent div targeting?

I have the following in React (using redux):
....
deleteBase(title) {
this.props.dispatch(removeBase(title));
}
render() {
const baseList = this.props.bases.map(base => {
return (
<li key={base.title} className="base">
<Link to={base.title}>{base.title}</Link>
<i
className="fas fa-times"
onClick={title => this.deleteBase(title)}
/>
</li>
);
});
}
In the dispatch function of removeBase I will need to have access to the single base.title from the clicked element. No matter how I try to get the right title transferred over to the function I can't do it.
return (
<ul className="baseWrapper">
{baseList}
<li className="add-list-wrapper">
<AddBase type="base" onAdd={title => this.addBase(title)} />
</li>
</ul>
);

Resources