Preview Image only works once, on the first drag.
EOMedvis opened this issue · comments
First of all, I would like to state I'm completely new the React development, and there are probably some really basic things I'm missing that is causing the problem I will show below. Please bare with my newbie ignorance if that is the case.
I have a draggable object defined below, that I created following the examples on the React DnD site:
import type { CSSProperties, FC } from "react";
import { DragPreviewImage, useDrag } from "react-dnd";
import { DraggableTypes } from "./DraggableTypes";
export interface CardProps {
cardData: CardType;
}
export const mainCardStyle: CSSProperties = {
border: '12px solid white',
outline: '3px solid white',
outlineOffset: '-20px',
borderRadius: '25px',
width: '65%',
height: '100%',
minWidth: '120px',
minHeight: '320px',
textAlign: 'center',
color: 'white',
backgroundImage: 'linear-gradient(to top, #396BE5, #ACA9E4)',
marginRight: '10px',
marginBottom: '10px',
cursor: 'move',
float: 'left',
boxShadow: '0px 5px 8px grey'
};
const innerDivStyle: CSSProperties = {margin: '10px'};
const imageDivStyle: CSSProperties = {marginTop: '40px',marginBottom: '20px'};
const titleDivStyle: CSSProperties = {marginBottom: '10px'};
function collectHandler(monitor: any) {
return {
isDragging: monitor.isDragging(),
handlerId: monitor.getHandlerId(),
};
}
export const DraggableCard: FC<CardProps> = function Card({ cardData }) {
const [{isDragging}, drag, preview] = useDrag(
function ()
{
return {
type: DraggableTypes.Card,
item: { cardData },
collect: collectHandler,
//end: (item, monitor) => { preview(null, { captureDraggingState: true });}, <== unsure about this.
};
},
[cardData]
);
const opacity = isDragging ? 0.4 : 1;
return (
<>
<DragPreviewImage connect={preview} src={cardData.image + ".png"} />
<div ref={drag} style={{ ...mainCardStyle, opacity }}>
<div style={innerDivStyle}>
<div style={imageDivStyle}>
<img src="placeHolder.png" alt="IconPlaceholder" />
</div>
<div style={titleDivStyle}>
<strong>{cardData.title}</strong>
</div>
<div>
{cardData.description}
</div>
</div>
</div>
</>
);
};
It's working, for the most part. I can drag it into a drop target and have stuff happened as I expected. The only problem is that if I drag the object, and let go without dropping it into the drop target, the next time I drag it, the preview image no longer works. Instead i just get a transparent copy of the draggable object that moves with my cursor, instead of the assigned preview image, as if I never assigned the preview image at all (it works as if this line: <DragPreviewImage connect={preview} src={cardData.image + ".png"} />, was completely removed from the code).
The draggable object is dynamically created from an array of data. So I'm not sure if Im supposed to clear data first each time I drop. I've asked Chat GPT for some insights and it told me I have to clear the preview and gave me the line I liked with the "<==". That hasn't fixed the issue, though.
I know React has some strangeness where if the data doesn't change, things don't rerender sometimes. I'm not sure if this is the issue. Am I doing something wrong, or is there some limitation in React DnD I'm not aware of? Thank you for your time. :)
@EOMedvis Please use key property on <DragPreviewImage key={new Date().getTime()} />
this will ensure the rerender on every drag
Oh. Awesome. Thank you for the solution!
I'm running into a second somewhat related problem. I am using an image for the preview and would like to scale it, but DragPreviewImage doesn't accept a CSS Style property (e.g. <DragPreviewImage style={{...style props}}>). Is there a way to scale the preview image without just editing the raw image itself? Or is there a better/different solution than using DragPreviewImage for a preview?
Actually, I think I fixed the PreviewImg not being scaled. I can scale and store an image as a src before feeding it to the DragPreviewImage and it seems to work.