If - else statement not appropriately working in ReactJS - javascript

I am displaying some data from an api using the If - else condition whereby the data should be loaded, and if nothing is found, a No data Found text should be displayed
But the problem is, the No Data Found text displays immediately the page is opened. It doesn't wait for the whole data from the api to load to appear. And when the data is loaded is when it disappears or stays if the data is not there.
How do I make the No Data Found text appear only after the data is loaded and verified to be null. Thanks.
Here is my code...
var showFarmList = '';
if (farmCount >= 1) {
showFarmList = user.farm.map((farm) => {
return (
<div className="col-6" key={farm.farmid}>
<div className="card card-dull card-height">
<Link to={`/farm-details/${user.username}/${farm.farmid}`}>
<div className="card-body">
<div className="farms-card">
<h5 className="card-title title-small truncate-1">{farm.farmname}</h5>
</div>
<p className="card-text truncate-3">{farm.county.countydescription}
</p>
</div>
</Link>
</div>
</div>
)
});
}
else {
showFarmList =
<>
<div className='row'>
No Data Found
</div>
</>
}
return (
<>
<div className="appHeader no-border transparent position-absolute">
<div className="left">
<a onClick={() => navigate(-1)} className="headerButton goBack">
<i className="fi fi-rr-cross"></i> </a>
</div>
<div className="pageTitle"></div>
</div>
<div id="appCapsule" className="mt-2">
<div className="section my-farmlist">
<h2>My Farms</h2>
<p className="my-farmtext">Here is a list of all the Farms you have registered on Tunda Care</p>
<div className="row">
{isLoading && <CardSkeleton cards={2} />}
{showFarmList}
</div>
</div>
</div>
</>
);
}
export default MyFarmList;
And here is the output.

I think this is what you expecting if I understood correctly.
Add !isLoading && to second part.
<div className="row">
{isLoading && <CardSkeleton cards={2} />}
{!isLoading && showFarmList}
</div>

Related

hide a div in react when there is no anchor tag in it

I have a react code (just a snippet, its not a complete code) as shown below which shows the list of programs on the webpage. Line A in the react code below renders all list of program on the webpage.
react code:
const renderPrograms = () => {
return programs.map((program, index)=>{
return (
<a href={program.url} key={index}>
<div className="program" >
<div class="hello-world">{program.name}</div>
</div >
</a>
)
})
}
return(
<div class="parent-div">
<div className ="pqr-xyz">
<h5>Hello World</h5>
</div>
<div className ="abc-def">
<h5>Programs</h5>
{programs && renderPrograms()} {/*Line A*/}
</div>
</div>
)
The above react code renders the following html code at runtime:
<div class="parent-div">
<div className ="pqr-xyz">
<h5>Hello World</h5>
</div>
<div class="abc-def">
<h5>Programs</h5>
<a href="https://www.google.com/">
<div class="program">
<div class="hello-world">TYUV</div>
</div>
</a>
<a href="https://www.twitter.com/">
<div class="program">
<div class="hello-world">SGHS</div>
</div>
</a>
</div>
</div>
Problem Statement:
When Line A does not render anything, my div (<div className ="abc-def">) will look like this at run time:
<div class="abc-def">
<h5>Programs</h5>
</div>
I am wondering what changes I need to make in my react code above so that when Line A doesn't render anything then <div class="abc-def"><h5>Programs</h5></div> should not display on the webpage.
They should be part of the condition:
return(
programs.length > 0 && <div className ="abc-def">
<h5>Programs</h5>
{renderPrograms()}
</div>
)
I changed the condition to check for length, otherwise you'll get a 0 instead of nothing, when empty
Try change this lines:
<div className ="abc-def">
<h5>Programs</h5>
{programs && renderPrograms()} {/*Line A*/}
</div>
into this:
{ programs && (
<div className ="abc-def">
<h5>Programs</h5>
{renderPrograms()} {/*Line A*/}
</div>
) }
Now without programs nothing is displayed.
You can try adding a className like this:
<div className={`abc-def ${programs.length ? "hidden" : ""}`}
Or from the parent componet, you can choose to not render this component with <div>
Instead of trying to hide it using CSS, you also can choose to not render it at all by returning nothing from your function
const RenderPrograms = ({ programs = [] }) => {
if (!programs.length) {
return []
}
return (
<div className="abc-def">
<h5>Programs</h5>
{programs.map((program, index) =>
<a href={program.url} key={index}>
<div className="program">
<div>{program.name}</div>
</div>
</a>
)}
</div>
)
}
ReactDOM.render(
<RenderPrograms />,
document.getElementById('react')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
You can try putting your class in a template string and using a ternary operator to display a certain class when some state value is true.
<div className={`${stateValue ? "name-of-class-with-hide" : "abc-def"}`}>
Here is a complete solution. All you need to do is move the <h5>Programs</h5> inside the condition and modify the condition slightly as shown in following snippet.
<div className ="abc-def">
{
programs.length > 0 && (
<div>
<h5>Programs</h5>
<RenderPrograms programs = {programs}/>
</div>
)
}
</div>
Note that I have modified the RenderPrograms function as well to accept arguments.
Following is a full snippet.
function RenderPrograms(props) {
return props.programs.map((program, index)=>{
return (
<a href={program.url} key={index}>
<div className="program" >
<div className="hello-world">{program.name}</div>
</div >
</a>
)
});
}
function MyApp() {
const programs=[
{name:'program 1', url: 'https://url1.com'},
{name:'program 2', url: 'url2'},
{name:'program 3', url: 'url3'},
];
const programs1 = []; // empty program list
return(
<div class="parent-div">
<h1>When programs list is not empty</h1>
{/*Above line is just for explanation -- you may remove it*/}
<div className ="pqr-xyz">
<h5>Hello World</h5>
</div>
<div className ="abc-def">
{
programs.length > 0 && (
<div>
<h5>Programs</h5>
<RenderPrograms programs = {programs}/>
</div>
)
}
</div>
{/*Below code is just for explanation -- you may remove it*/}
<hr />
<h1>When programs list is empty</h1>
<div className ="pqr-xyz">
<h5>Hello World</h5>
</div>
<div className ="abc-def">
{
programs1.length > 0 && (
<div>
<h5>Programs</h5>
<RenderPrograms programs = {programs1}/>
</div>
)
}
</div>
</div>
)
}
ReactDOM.render(
<MyApp />,
document.getElementById('app')
)
<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>
<div id="app"></div>
You need to move rendering of programs into RenderPrograms component. Make RenderPrograms component purelu functional and pass data to it via props (Instead of using function).
const RenderPrograms = ({ programs }) => {
let disp = programs.map((program, index) => {
return (
<a href={program.url} key={index}>
<div className="program">
<div class="hello-world">{program.name}</div>
</div>
</a>
);
});
return disp || <span />;
};
then use RenderPrograms to render programs in main component (One with logis for loading programs).
// let programs = [
// {
// url: "test1.com",
// name: "test1"
// },
// {
// url: "test2.com",
// name: "test2"
// }
// ];
let programs = [];
return (
<div className="App">
<div class="parent-div">
<div className="pqr-xyz">
<h5>Hello World</h5>
</div>
<div className="abc-def">
<h5>Programs</h5>
<RenderPrograms programs={programs} />
{/* {programs && renderPrograms()} Line A */}
</div>
</div>
</div>
);
You can play around with this sandbox

React - Show/hide when mouse hovers using hooks

I'm trying to create a show/hide div for when my mouse enters and leaves the container. I was following this example here (https://upmostly.com/tutorials/react-onhover-event-handling-with-examples) but I've run into a problem when I hover my mouse over the 'delete-container' div, it disappears. This problem occurs because it takes the action onMouseLeave. Is there a way I can fix this or possibly make my solution better? Here is a demo of what is happening (https://i.gyazo.com/528d909625b6b3828325c4e62894d1c3.mp4).
import React, { useState } from 'react';
import axios from 'axios';
export default function JobInfo({ jobs_info }) {
const [isShown, setIsShown] = useState(false);
const changeBackground = (x) => {
x.target.style.backgroundImage =
'linear-gradient(to right, #4639a7, #78019c)';
};
const changeBackground2 = (x) => {
x.target.style.background = 'rgb(37, 45, 73)';
};
return (
<div className='row'>
<div
className='container'
onMouseEnter={() => setIsShown(true)}
onMouseLeave={() => setIsShown(false)}
>
<div className='row'>
<div className='job-title'>{jobs_info.title}</div>
</div>
<div className='row wrapper'>
<div className='category-title'>Category</div>
<div className='location-title'>Location</div>
<div className='type-title'>Type of Job</div>
<div className='creator-title'>Job Creator</div>
</div>
<div className='row wrapper'>
<div className='category'>{jobs_info.job_team.title}</div>
<div className='location'>
{jobs_info.job_location.title}
</div>
<div className='type'>{jobs_info.job_work_type.title}</div>
<div className='creator'>{jobs_info.user.name}</div>
</div>
</div>
<div
className='counter-container'
id='counter-container'
onMouseEnter={changeBackground}
onMouseLeave={changeBackground2}
>
Candidates <br />
{jobs_info.candidates_count}
</div>
{isShown && (
<div className='delete-container center'>
<ion-icon id='trash' name='trash'></ion-icon>
</div>
)}
</div>
);
}
The issue happens because delete-container is outside of the container hierarchy and hence mouseleave event is triggered on the container. Render the delete-container as a child of container and style it accordingly
return (
<div className='row'>
<div
className='container'
onMouseEnter={() => setIsShown(true)}
onMouseLeave={() => setIsShown(false)}
>
<div className='row'>
<div className='job-title'>{jobs_info.title}</div>
</div>
<div className='row wrapper'>
<div className='category-title'>Category</div>
<div className='location-title'>Location</div>
<div className='type-title'>Type of Job</div>
<div className='creator-title'>Job Creator</div>
</div>
<div className='row wrapper'>
<div className='category'>{jobs_info.job_team.title}</div>
<div className='location'>
{jobs_info.job_location.title}
</div>
<div className='type'>{jobs_info.job_work_type.title}</div>
<div className='creator'>{jobs_info.user.name}</div>
</div>
{isShown && (
<div className='delete-container center'>
<ion-icon id='trash' name='trash'></ion-icon>
</div>
)}
</div>
<div
className='counter-container'
id='counter-container'
onMouseEnter={changeBackground}
onMouseLeave={changeBackground2}
>
Candidates <br />
{jobs_info.candidates_count}
</div>
</div>
);
However you could simply use CSS hover event to show or hide the delete-container without the need for state after renderingdelete-containeras a child ofcontainer`
.scss
.container {
.delete-container {
display: none;
// other styles
}
&:hover {
.delete-container {
display: block;
}
}
// other styles
}

Queried data disappears when webpack initially loads, then appears when I go to other page on website and return

Can anyone explain what's going on here?
On the index page referenced below there is a section where I source data from a WordPress API to generate the four most recent posts from a client. When running in develop mode with Gatsby, the website is presented fine, but when I upload the website to Netlify and build it out, the data disappears and leaves nothing more than an empty set of p tags.
When I go into development tools and step through breakpoints, I notice that the data in question appears on the website, but then disappears once the webpack fires and the modules are bundled. It's almost as if this data is getting overwritten. When I navigate away from this page on the same website, and then return, the p tags HAVE the data in question. I'm assuming the webpack overwrites the initial code, and then when I come back to the page the webpack has already fired so it loads the information fine? How do I work around this? Excuse me if this is a silly/obvious question.
Full code in reference:
import React from "react"
import { Link, graphql, useStaticQuery } from 'gatsby'
import Layout from '../components/layout'
import indexStyles from '../components/modules/index.module.css'
import Carousel from 'nuka-carousel'
import header1 from '../img/header1.jpg'
import header2 from '../img/header2.jpg'
import header3 from '../img/header3.jpg'
const IndexPage = () => {
const data = useStaticQuery(graphql`
query {
allWordpressPost (sort: {fields:date, order:DESC}) {
edges {
node {
title
slug
excerpt
date(formatString:"MMMM DD, YYYY")
}
}
}
}
`)
return (
<Layout>
<div className={indexStyles.indexCarousel_container}>
<Carousel
autoplay={true}
autoplayInterval={5000}
pauseOnHover={false}
wrapAround={true}
renderCenterLeftControls={({ previousSlide }) => (
<button onClick={previousSlide} className={indexStyles.indexCarousel_button}><i className="fas fa-arrow-left"></i></button>
)}
renderCenterRightControls={({ nextSlide }) => (
<button onClick={nextSlide} className={indexStyles.indexCarousel_button}><i className="fas fa-arrow-right"></i></button>
)}>
<div className={indexStyles.indexCarousel_slideContainer}>
<img src={header1} alt="Pencil case with cat, heart, and cupcake design."></img>
<div>
<h2>Shop</h2>
</div>
</div>
<div className={indexStyles.indexCarousel_slideContainer}>
<Link to="/blog"><img src={header2} alt="Notepad next to a cup of coffee."></img></Link>
<div>
<h2>Blog</h2>
</div>
</div>
<div className={indexStyles.indexCarousel_slideContainer}>
<img src={header3} alt="Colorful pencil cases."></img>
<div>
<h2>Cute Castle VIP</h2>
<p>Save 20%!</p>
</div>
</div>
</Carousel>
</div>
<h1 className={indexStyles.indexHeader}>Latest Posts</h1>
<div className={indexStyles.indexPost_container}>
<div className={indexStyles.indexPost_container}>
{data.allWordpressPost.edges.map((edge, i) => {
if (i < 4) {
return (
<div className={indexStyles.index_post}>
<h2><Link to={`/blog/${edge.node.slug}`} className={indexStyles.post_title} dangerouslySetInnerHTML={{ __html: edge.node.title }}></Link></h2>
<p className={indexStyles.post_date}>{edge.node.date}</p>
<p className={indexStyles.post_excerpt} dangerouslySetInnerHTML={{ __html: edge.node.excerpt }} />
<p><Link to={`/blog/${edge.node.slug}`} className={indexStyles.post_link}>Read more</Link></p>
</div>
)
}
})}
</div>
</div>
</Layout >
)
}
export default IndexPage
The section of code that disappears and reappears:
<div className={indexStyles.indexPost_container}>
<div className={indexStyles.indexPost_container}>
{data.allWordpressPost.edges.map((edge, i) => {
if (i < 4) {
return (
<div className={indexStyles.index_post}>
<h2><Link to={`/blog/${edge.node.slug}`} className={indexStyles.post_title} dangerouslySetInnerHTML={{ __html: edge.node.title }}></Link></h2>
<p className={indexStyles.post_date}>{edge.node.date}</p>
<p className={indexStyles.post_excerpt} dangerouslySetInnerHTML={{ __html: edge.node.excerpt }} />
<p><Link to={`/blog/${edge.node.slug}`} className={indexStyles.post_link}>Read more</Link></p>
</div>
)
}
})}
</div>
</div>
A link to the Netlify project.
https://zealous-engelbart-509321.netlify.com/
Thanks in advance for your help!

Ternary operator is not working in react js render function

We have a simple return render operation and we are deceding the return html using ternary operator, on the basis of state variable(anyException) value. Code snippet is shown below :
return <Form
validate={ formValidation }
onSubmit={this.onSubmit}
initialValues={initialValues}
render={({ handleSubmit, submitting, valid }) => (<form onSubmit={handleSubmit} className="k-form">
<div className="container-fixed">
(this.state.anyException ?
<ErrorDialogPopup
anyException={this.state.anyException}
errorInfo={this.state.errorInfo}
toggleErrorDialog={this.toggleErrorDialog.bind(this)}
/> : <div className="row">
{this.state.errorMessages.map(function(errorMessage) {
return <div className="errorMessage">{errorMessage}</div>
})}
</div>)
<div>
<div className="row">
<div className="col-sm-12">
<div className="panel panel-default" id="frmNetworkAdd">
<div className="panel-heading">
<h1 className="panel-title" id="panelHeader">
{this.state.networkId === -1? <span>Add Network</span> : <span>Edit Network</span>}
</h1>
</div>
But during run time, both the cases getting displayed. Could you please suggest what is going wrong here.
Instead of wrapping your ternary in (), use {} instead.
<div className="container-fixed">
{this.state.anyException ?
<ErrorDialogPopup
anyException={this.state.anyException}
errorInfo={this.state.errorInfo}
toggleErrorDialog={this.toggleErrorDialog.bind(this)}
/> : <div className="row">
{this.state.errorMessages.map(function(errorMessage) {
return <div className="errorMessage">{errorMessage}</div>
})}
</div>
}
</div>

Couldn't get rid of react warning of unique key in map

What's wrong with my below code? I had key={obj._id} and I expect I will not see the warning but I'm still getting it.
Warning: Each child in an array or iterator should have a unique "key"
prop. Check the render method..
renderListItems(items){
return(
<div>
{map(items, obj =>
<div key={obj._id} className="panel-body panel-row">
<div className="row">
<div className="col-md-12">
<h2 className="title">{obj.display_name}</h2>
<p className="edited">Last edited on {moment(obj.updated_at).format('DD MMM YYYY')}</p>
<div className="actions_wrap">
<Link to={`/mall-promospace/edit/${obj._id}`}>Edit</Link>
<a onClick={()=> this.setState({openConfirmationModal:true, selectedItemId: obj._id, selectedItemName: obj.display_name})}>Delete</a>
</div>
</div>
</div>
</div>
)}
</div>
)
}
I think you are coding some things wrong. You should apply the function "map" over an array.
Try this:
renderListItems(items){
return(
<div>
{items.map(obj =>
<div key={obj._id} className="panel-body panel-row">
<div className="row">
<div className="col-md-12">
<h2 className="title">{obj.display_name}</h2>
<p className="edited">Last edited on {moment(obj.updated_at).format('DD MMM YYYY')}</p>
<div className="actions_wrap">
<Link to={`/mall-promospace/edit/${obj._id}`}>Edit</Link>
<a onClick={()=> this.setState({openConfirmationModal:true, selectedItemId: obj._id, selectedItemName: obj.display_name})}>Delete</a>
</div>
</div>
</div>
</div>
)}
</div>
)
}
items.map((obj, i) => <div key={i}></div>)

Categories