How to use map() First map() parameter in Second map() method? - javascript

<div className='login'>
<p style={{paddingLeft: '30px'}}>login</p>
<ul>
{fetch.userData && fetch.userData.map((user, key)=><li key={key}>{user.login}</li>)}
</ul>
</div>
<div className='type'>
<p style={{paddingLeft: '30px'}}>type</p>
<ul>
{fetch.userData && fetch.userData.map((user, key)=><li key={key}>{user.type}</li>)}
</ul>
</div>
<div className='url'>
<p style={{paddingLeft: '30px'}}>url</p>
<ul>
{fetch.userData && fetch.userData.map((user, key)=><li key={key}>{user.url}</li>)}
</ul>
</div>
This is Firtst code But I am trying to do duplicate codes through map(). Like this..
{['login', 'type', 'url'].map(value => {
return (
<div className={value}>
<p style={{paddingLeft: '30px'}}>{value}</p>
<ul>
{fetch.userData && fetch.userData.map((user, key)=><li key={key}>{user.`${value}`}</li>)}
</ul>
</div>
)
})}
But I can't use First Parameter value in Second map() fetch.userData.map().
Any one know this problem??

Use user[value]
{fetch.userData && fetch.userData.map((user, key)=><li key={key}>{user[value]}</li>)}

Related

Calling data from the API for child component in Next.js

I am working on a header component. Here is the code:
import style from '../../styles/header.css';
import '../../styles/globals.css';
export default function Header({data}){
const [showMe, setShowMe] = useState(false);
function toggle(){
console.log("toggle")
setShowMe(!showMe);
}
return(
<>
<div className="header">
<div className="web-header">
<div className="first-header">
<div className="info-strip">
<ul>
<li>
Contact Us
</li>
<li>
7 Day Returns
</li>
<li>
Track Order
</li>
<li>
Return Order
</li>
<li>
Survey
</li>
</ul>
</div>
<div className="right-block d-flex">
<div className="login">
<span className="image"></span>
<span className="text">Log In
<div className="account-box">
</div>
</span>
</div>
<div className="cart">
<span className="cart-image">
</span>
<span className="text">Cart</span>
</div>
</div>
</div>
<div className="second-header">
<div className="header-logo">
<img src="https://www.mirraw.com/assets/logo-red.png" />
</div>
<div className="search">
<input placeholder="Search Something.." />
<button></button>
</div>
</div>
<div className="third-header">
<div className="container-fluid">
<ul className="menu">
{data.menus.map((post, index) => {
return (
<li className="menu-list">
{post.title}
<div className="megabox">
<ul className="wrapper">
{post.menu_columns.map((subItems, sIndex) => {
return <li>
<span className="menu-link">
{subItems.title}
</span>
<ul className="category">
{subItems.menu_items.map((x) => {
return <li>
{x.title}
</li>
})}
</ul>
</li>;
})}
</ul>
</div>
</li>)})}
</ul>
</div>
</div>
</div>
<div className="mobile-screen">
<div className="mobile-header">
<div className="mobile-menu">
<div className="menu-icon">
<div className="wrapper">
<input type="checkbox" id="navigation" />
<label for="navigation">
+
</label>
<div className="right-card">
<img src="https://www.mirraw.com/assets/logo-red.png" />
<p className="app-install">
<span>Download app</span>
</p>
<div className="cart">
<span className="cart-image"></span>
{/* <span className="text">Cart</span> */}
</div>
</div>
<nav>
<ul>
<li className="menu-heading">
<span>Menu</span>
<span>
<label for="navigation">X</label>
</span>
</li>
{data.menus.map((post, index) => {
return (
<li className="menu-list">
{post.title} <span onClick={toggle}>+</span>
<ul style={{display: showMe?"block":"none"}} className="category-one">
{post.menu_columns.map((subItems, sIndex) => {
return <li>
{subItems.title}
<span>+</span>
<ul className="category-two">
{subItems.menu_items.map((x) => {
return <li>
{x.title}
</li>
})}
</ul>
</li>;
})}
</ul>
</li>)})}
</ul>
</nav>
</div>
</div>
</div>
<div className="scroll-menu-list">
<ul className="mb-0">
{data.menus.map((post, index) => {
return (
<li className="menu-list">{post.title}</li>
)})}
</ul>
</div>
</div>
</div>
</div>
</>
)
}
export async function getServerSideProps() {
// Fetch data from external API
const res = await fetch(`https://api.mirraw.com/api/v1/menu`);
const data = await res.json();
// Pass data to the page via props
return { props: { data } }
}
Code is working fine if I render this page only, but when I import this component in other component, it threw error:
Server Error
TypeError: Cannot read property 'menus' of undefined
This error happened while generating the page. Any console logs will be displayed in the terminal window.
What could be the approach of getting value from the API for child component?
getServerSideProps can only be used within page components, which is why it works when you render this component as a page.
If you want to this to be a reusable component that can be called from other components and/or pages you'll need to pass the data you get at the page level (from getServerSideProps, for instance) down to it.
// pages/index.js
import Header from "../components/header"
export default function IndexPage({ data }) {
return (
<Header data={data} />
)
}
export async function getServerSideProps() {
const res = await fetch(`https://api.mirraw.com/api/v1/menu`);
const data = await res.json();
return { props: { data } }
}

Reactjs: Cannot read URL property of null, fetching from an API

I have products in json format that are fetched and shown in the frontend. In my products.json there is an image url for each products, but only some have image urls in them, others are empty. When I am looping the data in react I always get error in my react app saying Cannot read property of null in the tag, how do I write a logic that only renders the image when there is an image source else just return an empty div?
<ul>
{this.state.items.map((items, index) => {
return (
<li className="ProductList-product" key={items.id}>
<h3>{items.title}</h3>
<p>{items.description}</p>
<div className="price-box">
<p>from: {items.price} $</p>
</div>
<div>
{<img src={items.photo} alt=""/>}
{/* {console.log(items.photo.id)} */}
</div>
</li>
);
})}
</ul>
replace your
{<img src={items.photo} alt=""/>}
with
{items.photo && <img src={items.photo} alt=""/>}
it will only render img element when item.photo is not null.
You can set a condition. For example:
<ul>
{this.state.items.map((items, index) => {
return (
<li className="ProductList-product" key={items.id}>
<h3>{items.title}</h3>
<p>{items.description}</p>
<div className="price-box">
<p>from: {items.price} $</p>
</div>
{items.photo
? <div>
{<img src={items.photo} alt=""/>}
{/* {console.log(items.photo.id)} */}
</div>
: <div></div>
</li>
);
})}
</ul>

Mapping array inside array with React

I have a database in MongoDB and one of the props in the document contains an array. I'm trying to map the collection in the client-side using React using this code:
<div>
<h2>Recipes</h2>
<ul>
{this.state.recipes.map(recipe =>
<li key={recipe._id}>
{recipe.title}<br/>{recipe.category}<br/>
{recipe.ingredients}<br/>{recipe.preparation}
</li>
)}
</ul>
</div>
ingredients prop is an array and I want to map it too. How can I do it?
Any help would be great, thanks!
Just map it the same way you do with recipes
<div>
<h2>Recipes</h2>
<ul>
{this.state.recipes.map(recipe =>
<li key={recipe._id}>
{recipe.title}<br/>
{recipe.category}<br/>
{recipe.ingredients.map(ingredient => (
<span>{ingredient}</span>
))}
<br/>{recipe.preparation}
</li>
)}
</ul>
</div>
just map it again
<div>
<h2>Recipes</h2>
<ul>
{this.state.recipes.map(recipe =>
<li key={recipe._id}>
{recipe.title}<br/>
{recipe.category}<br/>
{recipe.ingredients.map(k =>(
<span key={k._id}>{k}<span>
)<br/>
{recipe.preparation}
</li>
)}
</ul>
</div>
<div>
<h2>Recipes</h2>
<ul>
{this.state.recipes.map(recipe =>
<li key={recipe._id}>
{recipe.title}<br/>{recipe.category}<br/>
{ recipe.ingredients.map(ingredient =>
<span>{ingredient}</span>
)}
<br/>{recipe.preparation}
</li>
)}
</ul>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
You can also use .map() there by calling recipe.ingredients.map() as the following:
{this.state.recipes.map(recipe =>
<li key={recipe._id}>
{recipe.title}<br/>{recipe.category}<br/>
{
recipe.ingredients.map((elem, index) =>
<div key={index}>
{elem /* or maybe elem['your-property-name'] if it's not a string */}
</div>
)
}<br/>{recipe.preparation}
</li>
)}
Also don't forget to add key={index} there to avoid the warning based on Lists and Keys.

Show if any conditions are present

I have been going back to some javascript docs to try and figure this out. But, no luck. What I am trying to do is, basically if any of the data is present show this jsx block.
{speaker.email || speaker.room &&
<>
<h3>Contact</h3>
<ul className="list-unstyled">
<li><a href={"mailto:speaker.email"}>{speaker.email}</a></li>
<li><span>{speaker.room} {speaker.building}</span></li>
<li>{speaker.phone}</span></li>
</ul>
</>
}
Is there a way using js or react to have multiple conditions using 'or'?
This is probably a terrible example but something like this:
{speaker.email || speaker.room || speaker.building || speaker.phone &&
#jmargolisvt was right, you can simply wrap with parens.
{(speaker.email || speaker.room || speaker.building || speaker.phone) &&
<>
...
</>
}
Simply, Use if condition and return the JSX
if (speaker.email || speaker.room || speaker.building || speaker.phone) { // any number of condition can be joined by ||
return (
<>
<h3>Contact</h3>
<ul className="list-unstyled">
<li><a href={"mailto:speaker.email"}>{speaker.email}</a></li>
<li><span>{speaker.room} {speaker.building}</span></li>
<li>{speaker.phone}</span></li>
</ul>
</>
);
}
I tested it and it worked like following. temp link https://codesandbox.io/s/determined-dhawan-k3yms
{speaker.email ||
(speaker.room && (
<>
<h3>Contact</h3>
<ul className="list-unstyled">
<li>
<a href={"mailto:speaker.email"}>{speaker.email}</a>
</li>
<li>
<span>
{speaker.room} {speaker.building}
</span>
</li>
<li>
<a href={speaker.phone}>
<span className="font-weight-bold">{speaker.phone}</span>
</a>
</li>
</ul>
</>
))}

How do I create an array and map over it to simplify my code?

I'm trying to improve my code according to some feedbacks of a reviewer of a course I'm studying.
So, I have this part of my code:
function Home(props) {
const [, setShowSearchPage] = useState(false);
return (
<div className="list-books">
<div className="list-books-title">
<h1>MyReads</h1>
</div>
<div className="list-books-content">
<div>
<div className="bookshelf">
<h2 className="bookshelf-title">Currently Reading</h2>
<div className="bookshelf-books">
<ol className="books-grid">
{props.books
.filter(book => book.shelf === 'currentlyReading')
.map(book => (
<li key={book.id}>
<Book
book={book}
changeShelf={props.changeShelf}
actualShelf="currentlyReading"
/>
</li>
))}
</ol>
</div>
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">Want to Read</h2>
<div className="bookshelf-books">
<ol className="books-grid">
{props.books
.filter(book => book.shelf === 'wantToRead')
.map(book => (
<li key={book.id}>
<Book
book={book}
changeShelf={props.changeShelf}
actualShelf="wantToRead"
/>
</li>
))}
</ol>
</div>
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">Read</h2>
<div className="bookshelf-books">
<ol className="books-grid">
{props.books
.filter(book => book.shelf === 'read')
.map(book => (
<li key={book.id}>
<Book
book={book}
changeShelf={props.changeShelf}
actualShelf="read"
/>
</li>
))}
</ol>
</div>
</div>
</div>
</div>
</div>
);
}
My question is:
Is there a stylish form for me to create an array of shelves info (the shelves are 'Current Reading', 'Want to Read' and 'Read') such as I could map over it and generate a block of code for each shelf, in order to avoid repeating the same code?
There are a ton of ways to refactor what you have, but here's what I think you're looking for:
function Home({books, changeShelf}) {
const [, setShowSearchPage] = useState(false)
const shelves = {
currentlyReading: 'Currently Reading',
wantToRead: 'Want to Read',
read: 'Read',
}
return (
<div className="list-books">
<div className="list-books-title">
<h1>MyReads</h1>
</div>
<div className="list-books-content">
<div>
{Object.keys(shelves).map(shelf => (
<div className="bookshelf">
<h2 className="bookshelf-title">{shelves[shelf]}</h2>
<div className="bookshelf-books">
<ol className="books-grid">
{books
.filter(book => book.shelf === shelf)
.map(book => (
<li key={book.id}>
<Book
book={book}
changeShelf={changeShelf}
actualShelf={shelf}
/>
</li>
))}
</ol>
</div>
</div>
))}
</div>
</div>
</div>
)
}
you can define render functions for not repeating same Code multiple times and it is easier to read
import React, { useState } from 'react';
import PropTypes from 'prop-types';
const propTypes = {};
const defaultProps = {};
function Component(props) {
const [, setShowSearchPage] = useState(false);
const renderBook = (book) => (
<li key={book.id}>
<Book book={book} changeShelf={props.changeShelf} actualShelf="currentlyReading" />
</li>
);
const renderBookShelf = (books, title) => (
<div className="bookshelf">
<h2 className="bookshelf-title">{title}</h2>
<div className="bookshelf-books">
<ol className="books-grid">{books.map(renderBook)}</ol>
</div>
</div>
);
return (
<div className="list-books">
<div className="list-books-title">
<h1>MyReads</h1>
</div>
<div className="list-books-content">
<div>
{renderBookShelf(props.books.filter((book) => book.shelf === 'currentlyReading'), 'Currently Reading')}
{renderBookShelf(props.books.filter((book) => book.shelf === 'wantToRead'), 'Want to Read')}
{renderBookShelf(props.books.filter((book) => book.shelf === 'read'), 'Read')}
</div>
</div>
</div>
);
}
Component.propTypes = propTypes;
Component.defaultProps = defaultProps;
export default Component;
I was stuck on a similar problem last year while working on NodeJS and Express.
You can use HTML tables rather than lists.
For populating the table, refer this answer.

Categories

Resources