reactjs - Förlorar touchmove-händelse i React-applikation


Jag har ett ganska stort projekt, något som ett rutnät skrivet i React med Typescript

Jag har ett div-element (som är en cell) med ontouchstart-händelse

render() {
    const matrix = this.props.cellMatrix;
    const disableUserSelectStyle: React.CSSProperties = {
        MozUserSelect: 'none',
        WebkitUserSelect: 'none',
        msUserSelect: 'none',
        userSelect: 'none'
    };
    // tslint:disable-next-line:jsx-wrap-multiline
    const content = (
        <div
            onKeyDown={e => this.handleKeyDown(e)}
            onKeyUp={e => this.handleKeyUp(e)}
            onCopy={e => this.handleCopy(e)}
            onCut={e => this.handleCut(e)}
            onPaste={e => this.handlePaste(e)}
            ref={ref => (this.gridElement = ref)}
            style={{
                ...this.props.style,
                ...disableUserSelectStyle,
                overflow: userIsMarkingGrid || columnIsMoving ? 'hidden' : 'auto'
            }}
            onScroll={_ => {
                this.handleScroll();
            }}
            data-cy="data-grid"
        >
            <div
                style={{ width: matrix.contentWidth, height: matrix.contentHeight, position: 'relative' }}
                onMouseDown={e => this.handleMouseDown(e)}
                onTouchStart={e => {
                    if (this.state.focusedLocation) {
                        this.handleTouchStart(e);
                    }
                }}
                onTouchEnd={e => this.handleTouchEnd(e)}
                onContextMenu={e => {
                    if (this.state.focusedLocation) {
                        this.handleContextMenu(e);
                        e.persist();
                    }
                }}
                onDoubleClick={e => this.handleDoubleClick(e)}
                onClick={e => this.handleClickCellOnlyForTouchDevices(e)}
                onMouseLeave={e => this.setState({ rowIdx: null })}
                ref={ref => (this.gridCellsContainerRef = ref)}
            >
                {matrix.frozenTopRange.height > 0 &&
                    this.renderRowPane(
                        { top: 0, position: 'sticky', zIndex: zIndex.horizontalPane },
                        matrix.frozenTopRange,
                        { bottom: true }
                    )}
                {matrix.scrollableRange.height > 0 &&
                    this.state.visibleRange &&
                    this.renderRowPane(
                        { height: matrix.scrollableRange.height },
                        matrix.scrollableRange.slice(this.state.visibleRange, 'rows'),
                        {}
                    )}
                {matrix.frozenBottomRange.height > 0 &&
                    this.renderRowPane(
                        { bottom: 0, position: 'sticky', zIndex: zIndex.horizontalPane },
                        matrix.frozenBottomRange,
                        { top: true, bottom: false }
                    )}
                {this.state.linePosition > 0 && this.renderLine()}
                {this.state.shadowPosition && this.renderShadow()}
                {this.state.currentBehavior.renderHiddenPart(
                    <div
                        className="hiddenElement"
                        contentEditable={true}
                        style={{ position: 'fixed', width: 1, height: 1, opacity: 0 }}
                        onBlur={e => {
                            if (this.state.isFocusedCellInEditMode) {
                                e.preventDefault();
                                e.stopPropagation();
                            }
                        }}
                        onPaste={e => e.preventDefault()}
                        ref={ref => (this.hiddenFocusElement = ref)}
                    />
                )}
            </div>
            {/* {this.renderCellContextMenu()} */}
        </div>
    );
    return content;
}
...
  1. efter att ha valt dessa celler sker omrendering efter setState, vilket ändrar beteendet i min applikation (val av cell)
  2. denna händelse tas emot inuti klassen, som inte är en komponent (beteende som ansvarar för att välja celler)
  3. sedan läggs touchmove-händelse till på fönstret, vilket inte utlöses omedelbart (detta är ett problem)
export class CellSelectionBehavior extends DelegateBehavior {
    private clientX = 0; // for gridScrollHandler!
    private clientY = 0;
    private touch: boolean = false;

    private moveHandler = this.handleMove.bind(this);

    constructor(grid: Grid, event: any, private selectionType: 'cell' | 'row' | 'column', touch?: boolean) {
        super(
            new AutoScrollBehavior(
                new BasicGridBehavior(grid),
                selectionType === 'row' ? 'vertical' : selectionType === 'column' ? 'horizontal' : 'both'
            )
        );

        const positionX =
            event.type === 'mousedown' || event.type === 'click'
                ? event.clientX
                : event.type === 'touchstart'
                ? event.changedTouches[0].clientX
                : null;
        const positionY =
            event.type === 'mousedown' || event.type === 'click'
                ? event.clientY
                : event.type === 'touchstart'
                ? event.changedTouches[0].clientY
                : null;

        this.clientX = positionX;
        this.clientY = positionY;
        if (touch) {
            this.touch = touch;
            if (event.type === 'click') {
                this.setFocusLocation(grid, positionX, positionY);
                window.addEventListener('click', this.clickHandler);
            } else if (event.type === 'touchstart') {
                window.addEventListener('touchmove', this.moveHandler);
                window.addEventListener('touchend', this.touchEndHandler);
                this.grid.gridElement.addEventListener('scroll', this.gridScrollHandler);
            }
        } else {
            this.handleMouseDown(event);

            if (event.shiftKey && this.grid.state.focusedLocation) {
                this.updateCellSelection();
            }
            this.grid.gridElement.addEventListener('scroll', this.gridScrollHandler);
        }
    }
}
  1. endast efter andra beröringen utlöses händelsen...

Jag betonar att allt fungerar bra med pointer events, men jag kan inte använda det eftersom det inte fungerar på Safari (iPads osv.)