How to do statement in a statement in react? - reactjs

I need to do a statement and print if the array is not empty, and if it's empty print an error message.
{isEmpty(this.props.items) ? errorMessage : working}
The simple idea is to replace working to:
{this.props.items && this.props.items.map((movie) => (
<Link to={`/movie/${movie.id}`} key={movie.id}>
<img className="Image-movie"
src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`}
alt={`${movie.title}`}/>
</Link>
))}
I try it to insert it but tells something about code syntax, any idea?

One of many solutions is to asign the second statement to a const
const items = this.props.items ? this.props.items.map((movie) => (
<Link to={`/movie/${movie.id}`} key={movie.id}>
<img className="Image-movie"
src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`}
alt={`${movie.title}`}/>
</Link>
)) : null
return {isEmpty(this.props.items) ? errorMessage : items}
Since the first check is not necessary you could just do
return !this.props.items.length ? error : this.props.items.map(/*...*/)

I think you can do that,
const {items} = this.props;
{items.length > 0 ? items.map((movie) => (
<Link to={`/movie/${movie.id}`} key={movie.id}>
<img className="Image-movie"
src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`}
alt={`${movie.title}`}/>
</Link>
)): (<Spinner /> || null) }

why you are checking again for props.items:
const renderItems = this.props.items.map((movie) => (
<Link to={`/movie/${movie.id}`} key={movie.id}>
<img className="Image-movie"
src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`}
alt={`${movie.title}`}/>
</Link>
))
{isEmpty(this.props.items) ? errorMessage : renderItems}

{this.props.items.length>0? this.props.items.map((movie) => (
<Link to={`/movie/${movie.id}`} key={movie.id}>
<img className="Image-movie"
src={sourcePath}
alt={movie.title}/>
</Link>)): errorMessage}

Related

conditional statements in a .map function returns nothing in React

I'm trying to do conditional rendering on react and although the condition it's either true or false, the elements are not being rendered.
What could be the problem? Thanks
<section>
<li className="top-nav__item top-nav__item--active">
{state.profileData[0].likes.map((like) => {
console.log(like) // outputs the user id and appState.user._id
like.user === appState.user._id ? (
<Link
onClick={(e) => startLikingTweet(e, tweetPost)}
to="/"
className="top-nav__link"
>
<IcomoonReact
className="top-nav__icon"
iconSet={iconSet}
color="red"
size={20}
icon="heart"
/>
<span>{tweetPost.likes.length}</span>
</Link>
) : (
<a>hey</a>
);
})}
</li>
</section>
You're missing a return statement inside of your .map, try adding a return before like.user === appState.user._id like the following:
I'm trying to do conditional rendering on react and although the condition it's either true or false, the elements are not being rendered. What could be the problem? Thanks
<section>
<li className="top-nav__item top-nav__item--active">
{state.profileData[0].likes.map((like) => {
console.log(like) // outputs the user id and appState.user._id
return like.user === appState.user._id ? (
<Link
onClick={(e) => startLikingTweet(e, tweetPost)}
to="/"
className="top-nav__link"
>
<IcomoonReact
className="top-nav__icon"
iconSet={iconSet}
color="red"
size={20}
icon="heart"
/>
<span>{tweetPost.likes.length}</span>
</Link>
) : (
<a>hey</a>
);
})}
</li>
</section>

Unique "key" prop not working for my array mapping - REACT

My unique key is not working for my array mapping.
The Link component is from react-scroll. I've therefore wrapped it into a tag, and setting the key here (thinking this could be where the issue is from)
I understand using index for setting a unique key is bad practice. But I am really just trying to remove the warning message a this point!
Any help would be very much appreciated.
My code:
import styles from '../styles/NavImage.module.css'
import { Link } from 'react-scroll'
const NAVLINKSHOVER = ['About', 'Club', 'Team', 'Timing', 'FAQ']
const NavImage = ({toggleFaq, toggleState, hoveredIndex, setHoveredIndex}) => {
const handleClick = () => {
toggleFaq();
};
return (
<nav className={styles.navbar}>
<div className={styles.linkContainer}>
{
NAVLINKSHOVER.map ((navLink, index) => {
if (navLink === 'FAQ') {
return (
toggleState?(
<div key={index}>
<Link
to="main"
smooth={true}
offset={0}
duration={0}
onClick={handleClick}
className={`${styles.navLinks} ${styles.linkNotActive}`}
>FAQ
</Link>
</div>
):(
<div key={index.toString()}>
<Link
to="faq"
smooth={true}
offset={500}
duration={200}
onClick={handleClick}
className={`${styles.navLinks} ${styles.linkNotActive}`}
>FAQ
</Link>
</div>
)
)
}
return (
<>
<a
className={`${styles.navLinks} ${hoveredIndex === index? styles.linkActive : styles.linkNotActive}`}
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(-1)}
key={index.toString()}
>
{navLink}
</a>
{
index!==NAVLINKSHOVER.length-1? <p className={styles.divider}> | </p> : null
}
</>
)
})
}
</div>
</nav>
);
}
export default NavImage;
You're returning a key in the case of FAQ, but not in any other cases; see here?
return (
<> <---- no key
<a
The top component returned needs a key. The string being iterated over would serve nicely without using the index.
{
NAVLINKSHOVER.map ((navLink, index) => {
if (navLink === 'FAQ') {
return (
toggleState?(
<div key="faq-main">
<Link
to="main"
smooth={true}
offset={0}
duration={0}
onClick={handleClick}
className={`${styles.navLinks} ${styles.linkNotActive}`}
>FAQ
</Link>
</div>
):(
<div key="faq">
<Link
to="faq"
smooth={true}
offset={500}
duration={200}
onClick={handleClick}
className={`${styles.navLinks} ${styles.linkNotActive}`}
>FAQ
</Link>
</div>
)
)
}
return (
<React.Fragment key={navLink}>
<a
className={`${styles.navLinks} ${hoveredIndex === index? styles.linkActive : styles.linkNotActive}`}
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(-1)}
key={index.toString()}
>
{navLink}
</a>
{
index!==NAVLINKSHOVER.length-1? <p className={styles.divider}> | </p> : null
}
</React.Fragment>
)
})
}
You should wrap the bottom return statement in a div and then give that div a key, if you want to get rid of the warning.
<div key={index.toString()}>
<a
className={`${styles.navLinks} ${
hoveredIndex === index ? styles.linkActive : styles.linkNotActive
}`}
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(-1)}
>
{navLink}
</a>
{index !== NAVLINKSHOVER.length - 1 ? (
<p className={styles.divider}> | </p>
) : null}
</div>
Pls note it is still a bad practice to use index as a key.

to unique useState variable for repeated item in ReactJS

I am newbie in reactjs. How can set a variable for every single iterating items?
I have some list and when click trash icon i want to show loading icon just for clicked item
const [deleteLoading, setDeleteLoading] = useState(false);
<ul className="mt-2">
{projects && projects.map((project, index) => (
<li key={index}>
<NavLink to={`someurl`}>{project.project_name}</NavLink>
<span className={`${deleteLoading ? "" : "hidden"}`}>
<svg> ..loading icon.. </svg>
</span>
<span onClick={() => deleteProject(project._id)} className={`${deleteLoading ? "hidden" : ""}`}>
<svg> ..trash icon.. </svg>
</span>
</li>)
)}
</ul>
when i clicked trash button it seems like
const deleteProject = async (id) => {
setDeleteLoading(true)
// some deleting code..
}
The behaviour you have is normal here because you use the same logic for every elements in your map function : ${deleteLoading ? "" : "hidden"}
If you want to have the delete icon only in the good project you should instead define a state var like deletingProject which contain the ID or the name of the deleting project.
Then you just have to modify the loading icon span like this :
<span className={`${project.project_id === deletingProject ? "" : "hidden"}`}>
I would suggest creating a component to hold each project, and add the delete functionality to the individual component. For example:
Project.js
export default function Project({ project, index }) {
const [deleteLoading, setDeleteLoading] = useState(false);
return (
<li key={index}>
<NavLink to={`someurl`}>{project.project_name}</NavLink>
<span className={`${deleteLoading ? "" : "hidden"}`}>
<svg> ..loading icon.. </svg>
</span>
<span onClick={() => deleteProject(project._id)} className={`${deleteLoading ? "hidden" : ""}`}>
<svg> ..trash icon.. </svg>
</span>
</li>
}
}
And then import into the Parent component
import Project from './Project.js'
export default function Parent(props) {
return (
<ul className="mt-2">
{projects && projects.map((project, index) => (
<Project project={project} index={index}/>
)}
</ul>
)
)}
I hope that helps
If you want to keep each project logic and state separate I'd suggest to create another component and host any project related logic there.
An example
function ProjectItem({ name }) {
const [deleteLoading, setDeleteLoading] = useState(false)
function handleDelete() {
// Some logic here
setDeleteLoading(true)
}
return (
<li>
<NavLink to={`someurl`}>{name}</NavLink>
<span className={`${deleteLoading ? "" : "hidden"}`}>
<svg> ..loading icon.. </svg>
</span>
<span
onClick={handleDelete}
className={`${deleteLoading ? "hidden" : ""}`}
>
<svg> ..trash icon.. </svg>
</span>
</li>
)
}
function MainComponent() {
return (
<ul className="mt-2">
{projects &&
projects.map((project) => (
<ProjectItem key={project._id} name={project.project_name} />
))}
</ul>
)
}
NOTES: Never use index as key prop in React Components. If you have an id already then use that as it's key value. Key prop is intended to be unique among all your rendered components
If you have items that can have it's own state move them to a new component. Hope you end up liking React and learning a lot my man ;3

Some div are created automatically in react

I have a react code like below
<div className="grid-container">
<header>
<Header />
</header>
<main>
{(userInfo?.isAdmin === false || !userInfo) &&
location.pathname === '/' && <Carousel />}
<div className={userInfo?.isAdmin ? 'row stretch left' : 'row'}>
{userInfo?.isAdmin && <Sidebar listItems={listItems} />}
<Content />
</div>
</main>
<footer className="row center">All rights reserved.</footer>
</div>
Output
In that screenshot, some div are created automatically. In component , There is no such a div in between sidebar class and row class. But I don't Know how it comes. Please help me..
Sidebar component:
export default function Sidebar(props) {
const items = props.listItems;
const location = useLocation();
return (
<ul className="sidebar">
{items.map((list) => (
<li key={list.link} className={`sidebar__item`}>
<Link
to={`/${list.link}`}
className={`sidebar__link ${
location.pathname === '/' && list.link === 'dashboard'
? 'active__link'
: location.pathname === '/' + list.link
? 'active__link'
: ''
}`}
>
{list.name === 'Dashboard' ? (
<ColumnsGap className="sidebar__icon" />
) : list.name === 'Products' ? (
<BoxSeam className="sidebar__icon" />
) : list.name === 'Orders' ? (
<BagCheck className="sidebar__icon" />
) : list.name === 'UsersList' ? (
<People className="sidebar__icon" />
) : (
''
)}
{list.name}
</Link>
</li>
))}
</ul>
);
}
Content Component:
export default function Content() {
const userSignin = useSelector((state) => state.userSignin);
const { userInfo } = userSignin;
return (
<>
<Route path="/product/:id" exact component={ProductScreen}></Route>
<Route path="/cart/:id?" exact component={CartScreen}></Route>
</>
);
}
ProductScreen:
export default function ProductScreen(props) {
return (
<>
{loading ? (
<LoadingBox></LoadingBox>
) : error ? (
<MessageBox>{error}</MessageBox>
) : (
<div className="">
<div className="row">
<div className="col-3">
<div className="col-1">Image</div>
<div className="col-1">Image Details</div>
</div>
<div className="col-1">
</div>
</div>
</div>)
}
Cart Component:
export default function CartScreen(props) {
return (
<div>
<h1 className="mb-1">Shopping Cart</h1>
<div className="row top">
<div className="col-2">
</div>
</div>
</div>)
}
Like above all components are enclosed with div tag or empty tag.But there are more empty div tag are produced automatically.

WP API in React Js (Gutenberg Editor) : Cannot read property 'wp:featuredmedia' of undefined even with condition

I've built a dynamic block in Gutenberg editor for latest custom posts.
And fetched featuredmedia for them through _embed.
So it's working if all my posts have featured image, but if not I have an error in console:
TypeError: Cannot read property 'wp:featuredmedia' of undefined
So I made condition, but having the same error.
What am I doing wrong? Here is my code:
import { Component } from '#wordpress/element';
import { __ } from '#wordpress/i18n';
import { withSelect } from '#wordpress/data';
class PortfolioPostsEdit extends Component {
render() {
const { posts, className } = this.props;
return (
<>
{(posts && posts.length > 0) ?
<div className={className}>
{posts.map(post => (
<article key={post.id}>
<a href={post.link}>
{post.title.rendered}
</a>
{post._embedded['wp:featuredmedia'] &&
<div className="image">
<img src={post._embedded['wp:featuredmedia'[0].source_url} />
</div>
}
</article>
))}
</div>
: <div>{__("No Posts Found", "my-blocks")}</div>
}
</>
)
}
}
export default withSelect(
(select, props) => {
return {
posts: select('core').getEntityRecords('postType', 'my_portfolio', 'per_page: 20', '_embed: true')
}
}
)(PortfolioPostsEdit);
I can't understand why my condition doesn't work:
{post._embedded['wp:featuredmedia'] &&
<div className="image">
<img src={post._embedded['wp:featuredmedia'[0].source_url} />
</div>
}
Can someone help me, please? Thanks.
This mean post._embedded is undefined. Try this:
post && post._embedded && post._embedded['wp:featuredmedia'] // make sure post._embedded is defined
Thank you!!!! worked great for me, I was puzzled with this for several days....
this is my working code for validating post contain feature image so I wont get any error in case we try to load a post that don't have a feature image set.
post && post._embedded && post._embedded['wp:featuredmedia']&&
{posts && posts.length > 0 ? (
<ul className={className}>
{posts.map(post => (
<li key={post.id}>
<a
target="_blank"
rel="noopener noreferrer"
href={post.link}
>
{decodeEntities(post.title.rendered)}
</a>
{
post && post._embedded && post._embedded['wp:featuredmedia']&&
<>
<img src={post._embedded['wp:featuredmedia'][0].source_url}/>
<span>{post._embedded['wp:featuredmedia'][0].title.rendered}</span>
</>
}
</li>
))}
</ul>
) : (
<div>
{" "}
{posts
? __("No Posts Found", "mytheme-blocks")
: __("Loading...", "mytheme-blocks")}{" "}
</div>
)}

Resources