From 29db20bb9badd14fb0232c238224bf97db1f7fa9 Mon Sep 17 00:00:00 2001
From: avivbiton <39068976+avivbiton@users.noreply.github.com>
Date: Mon, 19 Aug 2019 11:46:32 +0300
Subject: [PATCH 1/2] Dragscroll complete refactor
Refactor into functional component, using hooks, removed unnecessary binding and event listeners.
Added an option to disable on mobile (true by default)
---
src/DragScroll.jsx | 129 ++++++++++++++++-----------------------------
1 file changed, 46 insertions(+), 83 deletions(-)
diff --git a/src/DragScroll.jsx b/src/DragScroll.jsx
index dd69be4..40c1f48 100644
--- a/src/DragScroll.jsx
+++ b/src/DragScroll.jsx
@@ -1,89 +1,52 @@
-/**
- * Created by joe on 16/9/2.
- */
-
-import React from "react";
-
-export default class DragScroll extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- data: props.dataSource,
- dragging: false
- };
- }
-
- render() {
- let sytle = null;
- if (this.props.height && this.props.width) {
- sytle = {style: {height: this.props.height, width: this.props.width, overflow: 'auto'}};
+import React, { useState, useCallback, useRef, useMemo } from "react";
+
+export default function DragScroll({ className, children, mobileDisabled = true }) {
+
+ const [dragging, setDragging] = useState(false);
+ const [lastPosition, setPosition] = useState({ x: 0, y: 0 });
+ const container = useRef(null);
+
+ const isMobile = useMemo(() => {
+ return isDeviceMobile();
+ }, []);
+
+ const mouseUp = useCallback(() => {
+ if (dragging) {
+ setDragging(false);
+ }
+ }, [dragging]);
+
+ const mouseDown = useCallback(e => {
+ if (dragging === false) {
+ setDragging(true);
+ setPosition({ x: e.clientX, y: e.clientY });
+ }
+ }, [dragging]);
+ const mouseMove = useCallback(e => {
+ if (dragging) {
+ container.current.scrollLeft -= (-lastPosition.x + e.clientX);
+ container.current.scrollTop -= (-lastPosition.y + e.clientY);
+ setPosition({ x: e.clientX, y: e.clientY });
+ }
+ }, [container, dragging, lastPosition]);
+
+ if (mobileDisabled && isMobile) {
+ return
{children}
}
- return
- {this.props.children && this.renderChildren(this.props.children)}
-
;
- }
- componentDidMount() {
- window.addEventListener('mouseup', this.mouseUpHandle.bind(this));
- window.addEventListener('mousemove', this.mouseMoveHandle.bind(this));
- }
-
- componentWillUnmount() {
- window.removeEventListener('mouseup', this.mouseUpHandle.bind(this));
- window.removeEventListener('mousemove', this.mouseMoveHandle.bind(this));
- }
-
- mouseUpHandle(e) {
- if (this.state.dragging) {
- this.state.dragging = false;
- this.setState(this.state);
- }
- }
+ return (
+
+ {children}
+
+ );
- mouseDownHandle(e) {
- if (!this.state.dragging) {
- this.state.dragging = true;
- this.setState(this.state);
- this.lastClientX = e.clientX;
- this.lastClientY = e.clientY;
- e.preventDefault();
- }
- }
-
- mouseMoveHandle(e) {
- if (this.state.dragging) {
- this.refs.container.scrollLeft -=
- (-this.lastClientX + (this.lastClientX = e.clientX));
- this.refs.container.scrollTop -=
- (-this.lastClientY + (this.lastClientY = e.clientY));
- }
- }
+}
- renderChildren(dom, type) {
- if (this.isArray(dom)) {
- return dom.map((item, index) => {
- return React.cloneElement(item, {
- key: item.key || index,
- onMouseUp: this.mouseUpHandle.bind(this),
- onMouseDown: this.mouseDownHandle.bind(this)
- });
- });
- } else if ('object' == typeof dom) {
- return React.cloneElement(dom, {
- onMouseUp: this.mouseUpHandle.bind(this),
- onMouseDown: this.mouseDownHandle.bind(this)
- });
- }
- }
- isArray(object){
- return object && typeof object==='object' &&
- typeof object.length==='number' &&
- typeof object.splice==='function' &&
- //判断length属性是否是可枚举的 对于数组 将得到false
- !(object.propertyIsEnumerable('length'));
- }
+function isDeviceMobile() {
+ return window.matchMedia("(max-width: 992px)").matches;
}
From 48047f0c5f9b83b50eab2025e7cdf84d6e57f6a1 Mon Sep 17 00:00:00 2001
From: Aviv Biton <39068976+avivbiton@users.noreply.github.com>
Date: Mon, 19 Aug 2019 16:48:05 +0300
Subject: [PATCH 2/2] Moved mouseUp to window event to fix a bug
This fixes the bug that the scrollable will still be considered as "dragging" after you hold the mouse down and it leaves the scrollable area
---
src/DragScroll.jsx | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/DragScroll.jsx b/src/DragScroll.jsx
index 40c1f48..422f917 100644
--- a/src/DragScroll.jsx
+++ b/src/DragScroll.jsx
@@ -1,4 +1,4 @@
-import React, { useState, useCallback, useRef, useMemo } from "react";
+import React, { useEffect, useState, useCallback, useRef, useMemo } from "react";
export default function DragScroll({ className, children, mobileDisabled = true }) {
@@ -22,6 +22,7 @@ export default function DragScroll({ className, children, mobileDisabled = true
setPosition({ x: e.clientX, y: e.clientY });
}
}, [dragging]);
+
const mouseMove = useCallback(e => {
if (dragging) {
container.current.scrollLeft -= (-lastPosition.x + e.clientX);
@@ -30,13 +31,20 @@ export default function DragScroll({ className, children, mobileDisabled = true
}
}, [container, dragging, lastPosition]);
+ useEffect(() => {
+ window.addEventListener("mouseup", mouseUp, false);
+ return () => {
+ window.removeEventListener("mouseup", mouseUp, false);
+ }
+ }, [mouseUp]);
+
+
if (mobileDisabled && isMobile) {
return {children}
}
return (