Conditional styling in react map - javascript

I only want to show the display block on the hovered item. but when I hover it shows on every item in a map function. what I'm doing wrong.
basically, I just want to show hovered movie item's title. for now, it shows every movie when I hover.
MovieList.js
const [popular, setPopular] = useState([]);
const [hover, setHover] = useState(false);
return (
<>
<div className="movie-list">
<h2 style={{ fontSize: "49px", marginLeft: "60px" }}>What's Popular</h2>
<div className="popular">
{popular.map((pop, index) => (
<>
<div className="movie" key={index}>
<div className="tot" onMouseEnter={() => setHover(true)}>
<h4
id="pop-title"
style={{ display: hover ? "block" : "none" }}
key={index}
>
{pop.title}
</h4>
</div>
<img
src={"https://image.tmdb.org/t/p/w500" + pop.poster_path}
id="movie-img"
/>
</div>
</>
))}
</div>
</div>
</>
);
};
export default MovieList;

The same hover state variable is used for all your movies, so when it becomes true, all the movies are affected by the change. You could use something like an object instead of just a boolean to store one hover state per movie.
Another problem with your code that isn't helping:
You are missing a unique key prop on each item of the map (it must be on the direct child).
Solution 1: Remove the Fragment
Everything is already under one div so you don't need the React Fragment (<>) in that case. Also, you might wanna use something unique to the current map item other than the index in the array.
{popular.map((pop) => (
<div className="movie" key={pop.somethingUnique}>
<div className="tot" onMouseEnter={() => setHover(true)}>
<h4 id="pop-title" style={{ display: hover ? "block" : "none" }}>
{pop.title}
</h4>
</div>
<img
src={"https://image.tmdb.org/t/p/w500" + pop.poster_path}
id="movie-img"
/>
</div>
))}
Solution 2: Set the key on the Fragment
{popular.map((pop) => (
<Fragment key={pop.somethingUnique}>
<div className="movie">
<div className="tot" onMouseEnter={() => setHover(true)}>
<h4 id="pop-title" style={{ display: hover ? "block" : "none" }}>
{pop.title}
</h4>
</div>
<img
src={"https://image.tmdb.org/t/p/w500" + pop.poster_path}
id="movie-img"
/>
</div>
</Fragment>
))}

Related

How to append "active" class on first div using loop in Reactjs

I am working in Reactjs and using nextjs framework,right now i fetching data (videos) in slider and i want by default "active class" should be added to first value of array, In other words before click on slide i want by default value should "active" and should remove after click on "slide arrow" (< or >) button,How can i do this ? Here is my code
{this.state.trending.map((post, index) => {
return (
<>
<div class="carousel-item active">
<YouTube videoId={post.VideoId} opts={opts} />
</div>
</>
)
})}
This should work:
{this.state.trending.map((post, index) => {
return (
<>
<div class={`carousel-item ${index===0 ? "active" : ""`}>
<YouTube videoId={post.VideoId} opts={opts} />
</div>
</>
)
})}

React Recharts: Design custom tooltip

I am trying to replace recharts default tooltip with custom tooltip.
The existing tooltip looks like this.
I wanted to replace the above default tooltip as
I made sandbox for the code.
Thanks
Very quick solution. You can alter it as you want
Create a custom tooltip class
export const CustomTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) {
return (
<div className="custom-tooltip">
<p className="label">{`${label} : ${payload[0].value}`}</p>
<div>
{payload.map((pld) => (
<div style={{ display: "inline-block", padding: 10 }}>
<div style={{ color: pld.fill }}>{pld.value}</div>
<div>{pld.dataKey}</div>
</div>
))}
</div>
</div>
);
}
return null;
};
And use it like this
<Tooltip content={<CustomTooltip />} cursor={{ fill: "transparent" }} />
demo

Add popup in every item of flatlist in React

I would like to add a popup form in each item in the Flatlist, and the item is actually a card.
My problem is that every time, I clicked the button, the popup shows but, when my mouse moves out of the card, instead of showing the original one, it shows another popup whose parent is the whole page.
I know the problem should be that I need not set the variable setPopup properly. But I don't know how to fix it.
When my mouse is on the card:
enter image description here
When my mouse is out of the card, the popup will move up and its position will be based on the whole page:
enter image description here
Thank you!
This is my code.
const [buttonPopUp, setButtonPopUp] = useState(undefined);
const renderItem = (item, index) => {
return(
<Card key={index} style={{width: '20rem'}}>
<CardImg className='galleryPics' top src={galleryPic.img} alt="..."/>
<CardBody>
<PopUpEditGallery
gallery={item}
index = {index}
trigger={buttonPopUp}
setTrigger={setButtonPopUp}
>
Edit
</PopUpEditGallery>
<CardTitle className='cardTitle'>{item.title}</CardTitle>
<CardText className='cardText'>{item.description}</CardText>
<Button className="btn-round btn-icon" color="primary" size='sm' onClick={()=> setButtonPopUp(index)}>Edit</Button>
</CardBody>
</Card>
);
}
return (
<div>
<div>
<Header/>
</div>
<div className="container">
<div className="row">
<div className='col-7'>
<ul>
<FlatList
list={values.gallery}
renderItem={renderItem}/>
</ul>
</div>
</div>
</div>
</div>
)
code for popup
return (props.trigger != undefined) ? (
props.trigger == props.index &&
<div className='popup'>
<div className='popupInner'>
<form onSubmit={handleSubmit(onSubmit)}>
<FormGroup>
<Label>Title</Label>
<Input
type="text"
placeholder={prev.title}
onChange={val => props.setTitle(val.target.value, prev.idx)}
/>
</FormGroup>
<Button className="btn-round btn-icon" color="primary" size='sm'>
Submit
</Button>
<Button className="btn-round btn-icon" color="default" size='sm'>
Cancel
</Button>
</form>
</div>
</div>
): "";

react-beautiful-dnd: Prevent the rest of draggable items from reordering / moving up and replacing the item being dragged

In a single Droppable, I have mapped out an array of items, each as its own Draggable. My code is working properly and is doing what it's supposed to (i.e., I can move each Draggable individually). I'm just wondering if there's a way to stop the rest of my Draggables from "moving up" or replacing the empty spot the item-that's-being-dragged leaves behind.
Here's my code (DragDropContext is in another component, so it's not shown here):
<Droppable
droppableId='itemDroppable'
type='acceptsItems'
isDropDisabled={true} >
{(provided) =>
<div ref={provided.innerRef}>
{this.props.items.map((item, index) =>
<Draggable
key={item.id}
draggableId={item.name}
index={index} >
{provided =>
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps} >
{item.icon}
</div>
}
</Draggable>
)}
{provided.placeholder}
</div>
}
</Droppable>
And here's a video of what's happening:
As you can see, the rest of the following icons move up and replace the empty spot left by the item that's being dragged out of the Droppable. Is there a way to stop this? Ideally, I'd like to have the empty spot stay empty and not have the rest of the proceeding icons move up and fill up.
Thank you in advance!
I don't have a direct solution but I have an idea that may work around this problem.
when you are displaying the items using Array.map() function
first: suppose we add some additional information to the object to track if it's deleted.
add a condition so It renders the element if the flag is true.
Otherwise, a hidden element will be displayed.
note: I not sure but I think you can use provide.placeholder
for example:
{(provided) => (
<div ref={provided.innerRef}>
{this.props.items.map((item, index) => {
if (item.id !== 0) {
return (
<Draggable
key={item.id}
draggableId={item.name}
index={index}
>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
{item.icon}
</div>
)}
</Draggable>
);
} else
return (
<div style={{ width: '20px', height: '20px' }} /> //display hidden undraggable hidden element or try provided.placeholder
);
})}
{provided.placeholder}
</div>
)}
second: when you implement the deleting function inside onDragEnd() we can change the flag of that element.

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