reactjstypescriptonclickreact-grid-layout

React/TypeScript - react-grid-layout: onDrag is triggered when clicking the <div>


I am trying to build a grid with clickable and dragable itens using react-layout-grid component. But when I click the item the drag is instantly activated without actually moving the cursor.

Can someone help me to achieve it? Here is my code:

render() {
    return (
        <div className="gridL" style={{minHeight: '65px'}}>
          <StarIcon style={{ position: 'absolute', fontSize: 26, marginTop: 20, marginLeft: '5px', color: 'orange'}} />
          {this.props.favoritesData == null || 
          this.props.favoritesData.length == 0 && 
          (
              <div style={{ position: 'absolute', marginLeft: '35px', marginTop: '24px', height: '30px', color: 'gray'}}>
                Comece a adicionar favoritos para facilitar o acesso aos seus sistemas. 
                <img alt="hehehe" width={10} src="https://rastreio.grupoleonora.com.br/favicon.ico" />
              </div>
          )}
          <ResponsiveReactGridLayout
              {...this.props}
              layouts={this.state.layouts}
              cols={{ xl: 22, lg: 20, md: 16, sm: 12, xs: 8, xxs: 6 }}
              breakpoints={{ xl: 1400, lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
              rowHeight={50}
              isBounded={false}
              onDrag={this.onDrag}
              onDragStop={this.onDragStop}
              onLayoutChange={this.onLayoutChange}
              className="favorites-grid-layout"
              onBreakpointChange={this.onBreakpointChange}
              onDrop={this.onDrop}
              maxRows={1}
              verticalCompact={true}
              measureBeforeMount={false}
              isResizable={false}
              useCSSTransforms={true}
              compactType={"horizontal"}
              preventCollision={this.state.mounted}
              isDroppable={true}
              isDraggable={true}
              style={{ marginLeft: 25, minHeight: 55 }}
          >
            {Array.isArray(this.state.layouts[this.state.currentBreakpoint])
            ? this.generateDOM(this.state.layouts[this.state.currentBreakpoint])
            : null}
          </ResponsiveReactGridLayout>
        </div>
    );
  }

and generateDOM:

generateDOM(layouts: any) 
  {
    return layouts.map((el: any) => {
      const moduleId = this.props.modulesData?.find(q => q.id.toString() === el.i)?.id || -1;
      const isContextMenuOpen = this.state.contextMenus?.find(c => c.index?.toString() === el.i)?.index !== undefined &&
        this.state.contextMenus?.find(c => c.index?.toString() === el.i)?.index !== null;

      return (
        <div
          key={el.i}
          data-grid={el}
          onClick={() => !this.state.isDragging && !isContextMenuOpen && this.openFavorite(this.props.modulesData?.find(q => q.id.toString() === el.i)?.url)}
          onContextMenu={(e: any) => this.handleContextMenu(this.props.modulesData?.find(q => q.id.toString() === el.i)?.id || -1, e)}
          style={{ cursor: 'pointer' }}
        >
          <CardLinkFavoriteDisabled
            image={this.props.modulesData?.find(q => q.id.toString() === el.i)?.imageNavigation.filename}
            title={this.props.modulesData?.find(q => q.id.toString() === el.i)?.name}
          />
          <Menu
            PaperProps={{
              sx: {
                boxShadow: '0px 2px 10px 0px rgba(58, 53, 65, 0.1) !important',
                backgroundImage: 'linear-gradient(98deg, rgba(10,12,71,0.9), rgba(59,240,58,0.9) 160%)'
              },
            }}
            open={isContextMenuOpen}
            onClose={() => this.handleClose(moduleId)}
            anchorReference="anchorPosition"
            anchorPosition={
              this.props.modulesData?.find(q => q.id.toString() === el.i) !== null
                ? { top: this.state.contextMenus?.find(c => c.index === moduleId)?.mouseY || 0, left: this.state.contextMenus?.find(c => c.index === moduleId)?.mouseX || 0 }
                : undefined
            }
            elevation={0}
            componentsProps={{
              root: {
                onContextMenu: (e) => {
                  e.preventDefault();
                  this.handleClose(moduleId);
                },
              },
            }}
          >
            <MenuItem style={{ fontSize: 12, height: 15, color: 'white' }} onClick={(e) => { this.RemoveFavorite(e, moduleId) }}>
              <DeleteIcon color="error" />
              Remover
            </MenuItem>
          </Menu>
        </div>
      );
    });
  }

Problem: I cant click the div generated by generateDOM() because when I click it the drag function is activated and not the onClick event defined on the div.

Here is a live example of exactly the same problem I am facing (drag is activated onClick and not when moving): https://stackblitz.com/edit/react-grid-layout-bug-dragstart?file=index.tsx

Thank you.


Solution

  • if the drag is instantly activated without actually moving the cursor you can add onMouseUp and onMouseDown events to set the isDragging state.

    so that onClick event will be triggered if the item is not dragged.

    by using this events you can track if the item is getting dragged or not.

    If isDragging is 'true' item--> dragged. If isDragging is 'false' consider it as regular click.

    Hope this solves the problem!