react onmouseover while onmousedown

475 Views Asked by At

I'm trying to implement the same effect google sheets and ms excel has, that you press on one cell and move the mouse to highlight other close cells, the problem is when the onMouseDown event is fired and I'm still holding the mouse down and move the mouse over other cells - the onMouseOver cannot be fired, the mouse cursor itself turns into the not-allowed sign, any suggestions how to solve it?

Test.js

import React, { useRef } from 'react'

function Test() {
    const myTable = useRef(null)
    return (
            <>
            <table ref={myTable}>
                <tbody>
                    {
                        [...Array(4)].map((row, rowIndex) => (
                            <tr>
                                {
                                    [...Array(4)].map((col, colIndex) => (
                                        <td style={{
                                            border: '1px black solid',
                                            width: '100px',
                                            height: '100px'
                                          }}
                                            onMouseDown={(e) => console.log('mouse down')} 
                                            onMouseOver={(e) => console.log('mouse over')}>
                                        </td>
                                    ))
                                }
                            </tr>
                        )

                        )
                    }
                </tbody>
            </table>
        </>
    )
}

export default Test

2

There are 2 best solutions below

0
Kodak3993 On

problem solved by adding e.preventDefault()

0
Joshua Padron-Uy On

what I did was to create 2 divs/components that handle 2 mouse events separately. You might want to try a parent div that handles on mouse down and maybe a subparent div that contains the child you are targetting.

You will also need to use a global state to store the isMouseDownValue by using redux or react context. I got this idea initially from JavaScript event when mouseover AND mousedown

import { useSelector } from "react-redux";

import { StyledGridItem } from "../../../styles/styled-components/GridStyles.styled";
import { ITimeItem } from "../../../types/TimeItem";
import { SELECTION_CELL_TYPES } from "../../../enum/selection-cell";
import { useState } from "react";
import { IReduxState } from "../../../types/ReduxState";

interface IProps {
  item: ITimeItem | string;
  type: string;
}

const decideDisplay = (item: ITimeItem | string, type: string) => {
  switch (type) {
    case SELECTION_CELL_TYPES.TEXT:
      return item as string;
    case SELECTION_CELL_TYPES.TIMESLOT:
      return (item as ITimeItem).time;
    default:
      throw new Error("invalid cell selection type");
  }
};

const SelectionCell = ({ item, type }: IProps) => {
  const display = decideDisplay(item, type);
  const [isSelected, setIsSelected] = useState(false);

  const isMouseDown = useSelector(
    (state: IReduxState) => state.mouseDown.isMouseDown
  );

  const toggleSelectedHandler = () => {
    if (isMouseDown) {
      setIsSelected(true);
    } else {
      setIsSelected(false);
    }
  };

  return (
    <StyledGridItem isSelected={isSelected}>
      <div onMouseEnter={() => toggleSelectedHandler()}>{display}</div>
    </StyledGridItem>
  );
};

export default SelectionCell;



----------------------------------------------------------------------


another file...


import { useDispatch } from "react-redux";

import {
  setMouseDownTrue,
  setMouseDownFalse,
} from "../../store/slices/mouse-down-slice";
import OnMouseDownListenerStyles from "../../styles/OnMouseDownListener.module.css";

const OnMouseDownListener = ({ children }) => {
  const dispatch = useDispatch();

  return (
    <div
      onMouseDown={() => dispatch(setMouseDownTrue())}
      onMouseUp={() => dispatch(setMouseDownFalse())}
      className={OnMouseDownListenerStyles.rootContainer}
    >
      {children}
    </div>
  );
};

export default OnMouseDownListener;