Search code examples
javascriptreactjsreact-dnd

I need to fix drag and drop issue for backward case


I am using react-dnd for drag and drop I implemented that for my color code it's working but my issue is if I forward one color that works fine if I push that in any color but when I backward any color I need to take that color to the next the middle of two colors then will get an update but for forward I am not facing this issue I want to fix this for backward because if I change second color with first will not get updated you can check Code sandbox link as well

const HexCard = ({ hexCodes, index, moveCard }) => {
  const ref = useRef(null);
  const [{ isOver }, drop] = useDrop({
    accept: "card",
    drop: (item, monitor) => {
      if (!ref.current) return;
      if (!monitor.getDropResult()) {
        moveCard(item.index, index);
      }
    },
    collect: (monitor) => ({
      isOver: !!monitor.isOver({ shallow: true })
    })
  });
  const [{ isDragging }, drag] = useDrag({
    type: "card",
    item: () => {
      return { hexCodes, index };
    },
    collect: (monitor) => ({
      isDragging: monitor.isDragging()
    })
  });
  drag(drop(ref));
  return (
    <Grid
      item
      xs={4}
      sm={3}
      md={1}
      // eslint-disable-next-line react/no-array-index-key
      key={index}
      sx={{
        cursor: isDragging ? "grabbing !important" : "grab"
      }}
      ref={ref}
      position="relative"
    >
      <Box
        display="flex"
        justifyContent="center"
        component="span"
        sx={{
          backgroundColor: hexCodes,
          width: "50px",
          height: "40px"
        }}
      />
      {isOver && (
        <Box
          sx={{
            borderTop: "1px dotted",
            height: 2,
            position: "absolute"
          }}
        />
      )}
      <Box component="span">
        <Typography variant="body2">{hexCodes}</Typography>
      </Box>
    </Grid>
  );
};
HexCard.propTypes = {
  hexCodes: PropTypes.oneOfType([PropTypes.object]).isRequired,
  index: PropTypes.string.isRequired,
  moveCard: PropTypes.func.isRequired
};

const ColorPallete = () => {
  const [hexCodes, sethexCodes] = React.useState([
    "#668812",
    "#667788",
    "#345623",
    "#df11ac",
    "#dfac00",
    "#579470"
  ]);
  const [newHexCodes, setNewHexCodes] = React.useState([]);
  const [open, setOpen] = React.useState(false);

  const moveCard = useCallback((dragIndex, destIndex) => {
    sethexCodes((prevCards) => {
      const hexList = Object.values(prevCards);
      const draggedItem = hexList.splice(dragIndex, 1)[0];
      const updatedDestIndex = destIndex + (dragIndex > destIndex ? 1 : 0);
      hexList.splice(updatedDestIndex, 0, draggedItem);
      return hexList.reduce((obj, item, index) => {
        /* eslint-disable no-param-reassign */
        obj[index] = item;
        return obj;
      }, {});
    });
  }, []);
  return (
    <Grid container>
      <Grid item xs={12}>
        <Card>
          <CardContent sx={{ pl: 4 }}>
            <Box mb={2}>
              <Typography variant="h6">Current Colors</Typography>
            </Box>
            {Object.keys(hexCodes).length > 0 && (
              <Grid container>
                <DndProvider backend={HTML5Backend}>
                  {Object.keys(hexCodes).map((el, i) => (
                    <HexCard
                      key={JSON.stringify(i)}
                      index={i}
                      hexCodes={hexCodes[i]}
                      moveCard={moveCard}
                    />
                  ))}
                </DndProvider>
              </Grid>
            )}
          </CardContent>
        </Card>
      </Grid>
    </Grid>
  );
};

Solution

  • Make these changes to below mentioned method. i hope it works

    const moveCard = useCallback((dragIndex, destIndex) => {
            sethexCodes((prevCards) => {
              const hexList = Object.values(prevCards);
              const currentDragValue = hexList[dragIndex];
              const currentDestValues = hexList[destIndex];
              hexList[dragIndex] = currentDestValues;
              hexList[destIndex] = currentDragValue
              /* const draggedItem = hexList.splice(dragIndex, 1)[0];
              const updatedDestIndex = destIndex
              hexList.splice(updatedDestIndex, 0, draggedItem); */
              return hexList.reduce((obj, item, index) => {
                /* eslint-disable no-param-reassign */
                obj[index] = item;
                return obj;
              }, {});
            });
          }, []);