how to not display an element if it is undefined react - javascript

There is the following problem. I have 6 divs on the page, which may or may not contain an image. Let's say I have 3 pictures in the array and these pictures should be displayed in a div, and the remaining 3 elements should be a div (for example, with a background) I roughly solved it, but if this element is not found in the array, then the application crashes. Crashing because some element is missing. In the console, an error like sixb[3] is undefined.
Item Display
<div className='blocksix all'>
<img src={sixb[0].img} />
</div>
<div className='blocksix all'>
<img src={sixb[1].img} />
</div>
<div className='blocksix all'>
<img src={sixb[2].img} />
</div>
<div className='blocksix all'>
<img src={sixb[3].img} />
</div>
<div className='blocksix all'>
<img src={sixb[4].img} />
</div>
<div className='blocksix all'>
<img src={sixb[5].img} />
</div>
Array of elements
let [sixb , setsixb] = useState([
{img:"https://www.zonkpro.ru/zonk/assets/dice/mini/1.png"},
{id:2,title:2, img:"https://www.zonkpro.ru/zonk/assets/dice/mini/2.png" , style: 'none'},
{id:3,title:3, img:"https://www.zonkpro.ru/zonk/assets/dice/mini/3.png" , style: 'none'},
{id:4,title:4, img:"https://www.zonkpro.ru/zonk/assets/dice/mini/4.png" , style: 'none'},
{id:5,title:5, img:"https://www.zonkpro.ru/zonk/assets/dice/mini/5.png" , style: 'none'},
{id:6,title:6, img:"https://www.zonkpro.ru/zonk/assets/dice/mini/6.png" , style: 'none'},
])
No ideas yet how to solve

Try ternary operator and optional chaining
<div className='blocksix all'>
{sixb?.[1]?.img ? <img src={sixb[1].img} /> : <div className='some-background'>No image</div>}
</div>
Generic way of doing it -
{setsixb.map((item, index)=>{
retrun <div className='blocksix all' key={index}>
{item?.img ? <img src={item.img} /> : <div className='some-background'>No image</div>}
</div>
})
}

You can use conditional rendering in this scenario.
<div className='blocksix all'>
{sixb[0] && sixb[0].img && (<img src={sixb[0].img} />)}
</div>
Note:- Instead of writing the same div 6 times, just iterate over the array and display them.
{
sixb.map((each,index) => {
return (
<div key={index} className='blocksix all'>
{each && each.img && (<img src={each.img} />)}
</div>
)
})
}
For key, I have used index as you don't have any unique property in an object. If you can make the id mandatory then use id as the key.
This way the code is more clean and readable.

You should try this,
<>
{sixb.map((element, index) => element?.img ? <div key={index} className="block-image"><img src="img" /></div> : <div key={index} className="no-image">No Image found</div>)}
</>

Related

React, how to use if condition inside a div to change its className?

I am trying to get data using API and loop it for banner images.
I got the data. And it is working fine. Here is the code to get the data.
///Retrieving data using API
const [post, setPost] = useState(null);
useEffect(() => {
axios.get(global.url+'api/welcome').then(response => {
setPost(response.data);
});
}, []);
Now, I want to show images in the banner. In the first loop div class needs to <div className="carousel-item active"> as shown in the image. From the second loop active need to be removed to be like: <div className="carousel-item">.
////Looping for banner images
post[1].data.map((banner_image) => (
<div>
<div className="carousel-item active">
<img src="image source here" className="d-block w-100" alt="" />
</div>
</div> ))
In this case how to use the if condition? I am very new to React Js.
Thank you, in advance.
You could do conditions in your JSX as below. Notice the {} for className.
post[1].data.map((banner_image, index) => (
<div>
<div className={"carousel-item " + (index === 0 ? "active" : "")}>
<img src="image source here" className="d-block w-100" alt="" />
</div>
</div> ))
Try this
////Looping for banner images
post[1].data.map((banner_image, idx) => (
<div key={idx}>
<div className={`carousel-item ${idx === 0 ? "active" : ""}`}>
<img src="image source here" className="d-block w-100" alt="" />
</div>
</div> ))
You can use template literals in JSX.
post[1].data.map((banner_image, index) => (
<div key={`uui-${index}`}>
<div className={`carousel-item ${index === 0 ? 'active' : ''}`}>
<img src="image source here" className="d-block w-100" alt="" />
</div>
</div> ))

Having a loop to change the style of a card after every interval

Currently I have a container that holds my images in a particular pattern where the 1st and 6th card are horizontally elongated and cards 2 to 5 are vertically elongated. As of now all these images are hardcoded, but I want to have a .map function that will take the data from my backend. But the problem is .map takes 1 layout and duplicates it, but I want it to follow my particular pattern for which I assume I would need a loop.
CodeSandbox: https://codesandbox.io/s/gallant-forest-vygnw?file=/src/App.js
Code:
<div className="container">
<div className="row">
{/* {posts &&
posts.map((item) => ( */}
<div className="col-md-6 col-sm-6">
<div className="row">
<div className="col-md-12">
<img src="https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg" />
</div>
</div>
<div className="row">
<div className="col-md-6 col-sm-6">
<img
style={{ minHeight: "280px", objectFit: "cover" }}
src="https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg"
/>
</div>
<div className="col-md-6 col-sm-6">
<img
style={{ minHeight: "280px", objectFit: "cover" }}
src="https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg"
/>
</div>
</div>
</div>
<div className="col-md-6 col-sm-6">
<div className="row">
<div className="col-md-6 col-sm-6">
<img
style={{ minHeight: "280px", objectFit: "cover" }}
src="https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg"
/>
</div>
<div className="col-md-6 col-sm-6">
<img
style={{ minHeight: "280px", objectFit: "cover" }}
src="https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg"
/>
</div>
</div>
<div className="row">
<div className="col-md-12">
<img src="https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg" />
</div>
</div>
</div>
{/* ))} */}
</div>
</div>
try using index in map to customize how you want it.
posts.map((item, idx) => (
<div className={idx === 0 ? "col-md-12" : "col-md-6 col-sm-6"}>
<img
src={item?.src}
alt={item?.caption}
style={{ minHeight: "280px", objectFit: "cover" }}
/>
</div>
Codesandbox
https://codesandbox.io/s/sad-shannon-wkc28?file=/src/App.js
I'm not use to help on this site but i maybe have an answer for you.
It seems your 'posts' only have 3 items so mapping on this wont make you have the 6 images you need. Whatever, you said the datas have to come frome your backend so i presume it's just some testing data.
I suggest you to use .map normally but define the differences with CSS. Then you can easily select the first and the last element of your mapping with something like that :
container div:first-child div:first-child, container div:last-child div:last-child{
//your css
}
But as you using bootsrap for styling, you need to translate the bootstrap classes for this method. I suggest you an other. The .map function can get an index as second argument. So you can do something like this :
posts.map(element, i => {yourcode} )
Then use the index for knowing if it is the first or the last item in a ternary expression :
i === 0 || i === posts.length ? your code for the first and last : normal code for the others
EDIT:
I've try in the sandbox, it seems the problem with your patern is that every elements are not independents. The div element who appears every 3 items screw up everything for using map. My best result was this :
return (
<div className="App">
<div className="container">
<div className="row">
{posts &&
posts.map((item, i) => {
return (i+1)%4 === 0 || i===0 ?
(
<div className="col-md-6 col-sm-6">
<div className="row">
<div className={ i === 0 || i === (posts.length-1) ? "col-md-12" : "col-md-6 col-sm-6"}>
<img src="https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg" />
</div>
</div>
</div>
)
:
(
<div className="row">
<div className={ i === 0 || i === (posts.length-1) ? "col-md-12" : "col-md-6 col-sm-6"}>
<img src="https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg" />
</div>
</div>)
})}
</div>
</div>
</div>
);
But i can't figuring out how handle this parent div for encapsulating every 3 element. Here a suggestion that i've not trying yet :
Create a component who will mapping inside the problematic div.
Find a way to create a 2D Array with your request, each Array in this one composed by 3 elements
Mapping the 2D Array using your component.
The first mapping will map over each Array in your 2D array and the second map, inside your component, will map over the elements.

How to change color icons in react after onClick

export default function Post({post}) {
const [like,setLike] = useState(post.like)
const [islike,setIslike] = useState(false)
const handler=()=>{
setLike(islike? like-1:like+1 )
setIslike(!islike)
}
return (
<>
<div className="postcontainer">
<div className='postwrapper'>
<div className="postTop">
<div className="topleft">
<img className="images" src= {Users.filter((u)=> u.id === post.userId)[0].imagesProfile} alt="profile" />
<span className="names"> {Users.filter((u)=> u.id === post.userId)[0].userName} </span>
<span className="dates"> {post.date}</span>
</div>
<div className="topzRight">
<MoreVert />
</div>
</div>
<div className="postcenter">
<span className='text'>{post.descrip}</span>
<img className="imagepost" src={post.imagesPost} alt="newpost" />
</div>
<div className="postbotton">
<div className="postbottonLeft">
<LocationOnIcon className="icon" />
<FavoriteIcon className="icon" onClick={handler}/>
<span className='counter' > {like} People liked it</span>
</div>
<div className="postbottonRight">
<span>{post.comment} comments</span>
<SmsOutlined className="iconcomment" />
</div>
</div>
</div>
</div>
</>
)
First, you should try to talk more about what you want to do in the code instead of just putting the question in the title and putting the code as the body.
Second, if you want some HTML element to have a different color based on when you clicked it or not, you could make a CSS class for each state you want, so one class could be .isLiked and the other can be .isNotLiked with each one having a different color. Then in your code, you can have a conditional on the className attribute for the HTML element to decide what it should be based on a conditional.
Eg: className={isLiked ? 'isLiked' : 'isNotLiked'}

Problem on React, onClick take the last var and note the choosen one

const CharacterList = () => {
const [change, setChange] = React.useState(false);
const QuickSilver= () => setChange(!change);
const SuperMan= () => setChange(!change);
return (
<div id="character" className="list">
<img id="icons" className="one" src={QuickSilverIc} onClick={QuickSilver} />
{change && (
<img className="card" src={QuickSilverStat} />
)}
<img id="icons" className="two" src={SuperManIc} onClick={SuperMan} />
{change && (
<img className="card" src={SuperManStat} />
)}
So, when i click on the QuickSilver img that bring me the img with src={SuperManStat} and not {QuickSilverStat}
If anyone can help me it will be very nice !
ps: yeah i've cut the react components to show you only what i want ofc ive done averything correctly, like import export etc...
what you need to do is create to different useStates one for quicksilver and the other one for superman, or create an object with this shape
const [hero, SetHero] = useState({superman: false, quicksilver:false});
and then in your onClickhandler you can pass the name and update the state to right hero
{change ? (
<>
<img id="icons" className="one" src={QuickSilverIc} onClick={QuickSilver} />
<img className="card" src={QuickSilverStat} />
</>
) : (
<>
<img id="icons" className="two" src={SuperManIc} onClick={SuperMan} />
<img className="card" src={SuperManStat} />
</>
)}
As I understand, you want to show only one of them. To achieve this, you should wrap both images of each one together, and show only one of them on each change value (true or false):
{change && (
<div>
<img id="icons" className="one" src={QuickSilverIc} onClick={QuickSilver} />
<img className="card" src={QuickSilverStat} />
</div>
)}
{!change && (
<div>
<img id="icons" className="two" src={SuperManIc} onClick={SuperMan} />
<img className="card" src={SuperManStat} />
</div>
)}

Filter condition in Reactjs

I'm trying to execute if the table has data or not. If there's data only that table will show the other will stay on no records found and vice versa. I feel like I'm wrong about my condition.
render() {
const { legal_records } = this.props;
return (
<div className="row">
<div className="col">
<div className="card">
<div className="card-body">
{legal_records.size ? (
<div
className="table-responsive"
style={{ overflowX: "hidden", maxHeight: 600 }}
>
<LegalService
data={legal_records}
onSettle={this.onSettle}
/>
</div>
) : (
<div className="no-content text-center my-3">
<i className="material-icons">find_in_page</i>
<h6 className="text-muted">No Record Found</h6>
</div>
)}
</div>
<div className="card-body">
{legal_records.size ? (
<div
className="table-responsive"
style={{ overflowX: "hidden", maxHeight: 600 }}
>
<LegalDivision
data={legal_records}
onSelectPay={this.onSelectPay}
/>
</div>
) : (
<div className="no-content text-center my-3">
<i className="material-icons">find_in_page</i>
<h6 className="text-muted">No Record Found</h6>
</div>
)}
</div>
</div>
</div>
</div>
);
}
}
If legal_records is an array, you need to access .length instead:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length
change the condition to:
legal_records.length > 0
Assuming that legal_records is an array:
legal_records.size should be legal_records.length
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length
Assuming that legal_records is an object you could do something like this:
Object.entries(legal_records).length > 0
Which will determine whether or not an object has any items in it.
See the docs on Object.entries(...) here.
Though, without knowing the type of legal_records it's hard to give an appropriate answer.

Categories

Resources